├── .ipynb_checkpoints ├── PyXspecWalkthrough1-checkpoint.ipynb ├── PyXspecWalkthrough1Matplotlib-checkpoint.ipynb ├── PyXspecWalkthrough2-checkpoint.ipynb ├── PyXspecWalkthrough2Matplotlib-checkpoint.ipynb ├── PyXspecWalkthrough3-checkpoint.ipynb ├── PyXspecWalkthrough4-checkpoint.ipynb ├── PyXspecWalkthrough5-checkpoint.ipynb └── README-checkpoint.md ├── PyXspecIXPEPolarPlot.ipynb ├── PyXspecWalkthrough1.ipynb ├── PyXspecWalkthrough1Matplotlib.ipynb ├── PyXspecWalkthrough2.ipynb ├── PyXspecWalkthrough2Matplotlib.ipynb ├── PyXspecWalkthrough3.ipynb ├── PyXspecWalkthrough4.ipynb ├── PyXspecWalkthrough4Matplotlib.ipynb ├── PyXspecWalkthrough5.ipynb ├── README.md ├── data ├── aciss.fak ├── aciss_aimpt_cy15.arf ├── aciss_aimpt_cy15.rmf ├── det1_filt_src.arf ├── det1_filt_src.mrf ├── det1_filt_src_I.pha ├── det1_filt_src_Q.pha ├── det1_filt_src_U.pha ├── det2_filt_src.arf ├── det2_filt_src.mrf ├── det2_filt_src_I.pha ├── det2_filt_src_Q.pha ├── det2_filt_src_U.pha ├── det3_filt_src.arf ├── det3_filt_src.mrf ├── det3_filt_src_I.pha ├── det3_filt_src_Q.pha ├── det3_filt_src_U.pha ├── ginga_lac.rsp ├── hisum.pha ├── ixpe_d1_20170101_alpha075_02.rmf ├── ixpe_d2_20170101_alpha075_02.rmf ├── ixpe_d3_20170101_alpha075_02.rmf ├── losum.pha ├── pgplot.svg ├── s54405.pha ├── s54405.rsp ├── test.fak └── test1.fits └── pyxspecTutorials ├── PyXspec-TheExtendedTutorial.ipynb ├── PyXspecUserGuide-QuickTutorial.ipynb ├── README.md └── data ├── spec.pha ├── spec.rmf ├── spec2.pha ├── spec2_bkg.pha ├── spec3.pha ├── spec3.rmf ├── spec3_bkg.pha ├── spec_bkg.pha ├── spec_sim.pha └── spec_sim_bkg.pha /.ipynb_checkpoints/PyXspecWalkthrough2Matplotlib-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# uncomment the line below to make matplotlib plots dynamic\n", 10 | "#%matplotlib notebook\n", 11 | "import matplotlib\n", 12 | "import numpy as np\n", 13 | "import matplotlib.pyplot as plt\n", 14 | "\n", 15 | "# older versions of Jupyter may need wurlitzer in order to redirect the C output to the notebook\n", 16 | "# %load_ext wurlitzer\n", 17 | "\n", 18 | "from xspec import *" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "##Simultaneous Fitting\n", 26 | "\n", 27 | "XSPEC has the very useful facility of allowing models to be fitted simultaneously to more than one data file. It is even possible to group files together and to fit different models simultaneously. Reasons for fitting in this manner include:\n", 28 | "\n", 29 | " The same target is observed at several epochs but, although the source stays constant, the response matrix has changed. When this happens, the data files cannot be added together; they have to be fitted separately. Fitting the data files simultaneously yields tighter constraints.\n", 30 | " The same target is observed with different instruments. All the instruments on Suzaku, for example, observe in the same direction simultaneously. As far as XSPEC is concerned, this is just like the previous case: two data files with two responses fitted simultaneously with the same model.\n", 31 | " Different targets are observed, but the user wants to fit the same model to each data file with some parameters shared and some allowed to vary separately. For example, if we have a series of spectra from a variable AGN, we might want to fit them simultaneously with a model that has the same, common photon index but separately vary the normalization and absorption.\n", 32 | "\n", 33 | "Other scenarios are possible--the important thing is to recognize the flexibility of XSPEC in this regard.\n", 34 | "\n", 35 | "As an example we will look at a case of fitting the same model to two different data files but where not all the parameters are identical. Again, this is an older dataset that provides a simpler illustration than more modern data. The massive X-ray binary Centaurus X-3 was observed with the LAC on Ginga in 1989. Its flux level before eclipse was much lower than the level after eclipse. Here, we'll use XSPEC to see whether spectra from these two phases can be fitted with the same model, which differs only in the amount of absorption. The spectra and corresponding response matrices were obtained from the HEASARC and are available from https://heasarc.gsfc.nasa.gov/docs/xanadu/xspec/walkthrough.tar.gz\n", 36 | "\n", 37 | "This kind of fitting relies on introducing an extra dimension, the group, to the indexing of the data files. The files in each group share the same model but not necessarily the same parameter values, which may be shared as common to all the groups or varied separately from group to group. Although each group may contain more than one file, there is only one file in each of the two groups in this example. Groups are specified with the data command, with the group number preceding the file number, like this: " 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 2, 43 | "metadata": {}, 44 | "outputs": [ 45 | { 46 | "name": "stdout", 47 | "output_type": "stream", 48 | "text": [ 49 | "/Users/karnaud/Jupyter-notebooks/data\n", 50 | "\n", 51 | "2 spectra in use\n", 52 | " \n", 53 | "Spectral Data File: losum.pha Spectrum 1\n", 54 | "Net count rate (cts/s) for Spectrum:1 1.401e+02 +/- 3.549e-01\n", 55 | " Assigned to Data Group 1 and Plot Group 1\n", 56 | " Noticed Channels: 1-48\n", 57 | " Telescope: GINGA Instrument: LAC Channel Type: PHA\n", 58 | " Exposure Time: 1 sec\n", 59 | " Using fit statistic: chi\n", 60 | " Using Response (RMF) File ginga_lac.rsp for Source 1\n", 61 | "\n", 62 | "Spectral Data File: hisum.pha Spectrum 2\n", 63 | "Net count rate (cts/s) for Spectrum:2 1.371e+03 +/- 3.123e+00\n", 64 | " Assigned to Data Group 2 and Plot Group 2\n", 65 | " Noticed Channels: 1-48\n", 66 | " Telescope: GINGA Instrument: LAC Channel Type: PHA\n", 67 | " Exposure Time: 1 sec\n", 68 | " Using fit statistic: chi\n", 69 | " Using Response (RMF) File ginga_lac.rsp for Source 1\n", 70 | "\n" 71 | ] 72 | } 73 | ], 74 | "source": [ 75 | "%cd data\n", 76 | "AllData(\"1:1 losum 2:2 hisum\")" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "Here, the first group makes up the file losum.pha, which contains the spectrum of all the low, pre-eclipse emission. The second group makes up the second file, hisum.pha, which contains all the high, post-eclipse emission. Note that file number is \"absolute\" in the sense that it is independent of group number. Thus, if there were three files in each of the two groups (lo1.pha, lo2.pha, lo3.pha, hi1.pha, hi2.pha, and hi3.pha, say), rather than one, the six files would be specified as \"1:1 lo1 1:2 lo2 1:3 lo3 2:4 hi1 2:5 hi2 2:6 hi3\". The ignore method works on file number, and does not take group number into account. So, to ignore channels 1-3 and 37-48 of both files: " 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 3, 89 | "metadata": { 90 | "scrolled": true 91 | }, 92 | "outputs": [ 93 | { 94 | "name": "stdout", 95 | "output_type": "stream", 96 | "text": [ 97 | " 3 channels (1,3) ignored in spectrum # 1\n", 98 | " 3 channels (1,3) ignored in spectrum # 2\n", 99 | " 12 channels (37,48) ignored in spectrum # 1\n", 100 | " 12 channels (37,48) ignored in spectrum # 2\n", 101 | "\n" 102 | ] 103 | } 104 | ], 105 | "source": [ 106 | "AllData.ignore(\"1-3 37-48\")" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "The model we'll use at first to fit the two files is an absorbed power law with a high-energy cut-off: " 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 4, 119 | "metadata": {}, 120 | "outputs": [ 121 | { 122 | "data": { 123 | "text/plain": [ 124 | "" 125 | ] 126 | }, 127 | "execution_count": 4, 128 | "metadata": {}, 129 | "output_type": "execute_result" 130 | }, 131 | { 132 | "name": "stdout", 133 | "output_type": "stream", 134 | "text": [ 135 | "\n", 136 | "========================================================================\n", 137 | "Model phabs<1>*highecut<2>*powerlaw<3> Source No.: 1 Active/On\n", 138 | "Model Model Component Parameter Unit Value\n", 139 | " par comp\n", 140 | " Data group: 1\n", 141 | " 1 1 phabs nH 10^22 1.00000 +/- 0.0 \n", 142 | " 2 2 highecut cutoffE keV 10.0000 +/- 0.0 \n", 143 | " 3 2 highecut foldE keV 15.0000 +/- 0.0 \n", 144 | " 4 3 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 145 | " 5 3 powerlaw norm 1.00000 +/- 0.0 \n", 146 | " Data group: 2\n", 147 | " 6 1 phabs nH 10^22 1.00000 = p1\n", 148 | " 7 2 highecut cutoffE keV 10.0000 = p2\n", 149 | " 8 2 highecut foldE keV 15.0000 = p3\n", 150 | " 9 3 powerlaw PhoIndex 1.00000 = p4\n", 151 | " 10 3 powerlaw norm 1.00000 = p5\n", 152 | "________________________________________________________________________\n", 153 | "\n", 154 | "\n", 155 | "Fit statistic : Chi-Squared 3.256708e+08 using 33 bins.\n", 156 | " Chi-Squared 4.084839e+06 using 33 bins.\n", 157 | "Total fit statistic 3.297556e+08 with 61 d.o.f.\n", 158 | "\n", 159 | "Test statistic : Chi-Squared 3.297556e+08 using 66 bins.\n", 160 | " Null hypothesis probability of 0.000000e+00 with 61 degrees of freedom\n", 161 | " Current data and model not fit yet.\n" 162 | ] 163 | } 164 | ], 165 | "source": [ 166 | "Model(\"phabs * highecut(pow)\")" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "Notice how the summary of the model, displayed immediately above, is different now that we have two groups, as opposed to one. We can see that of the 10 model parameters, 5 for each data group and, by default, the parameters for the second data group are linked to those for the first. Let us suppose that we have a theory that the difference between the two spectra is a change in the absorption. We want to remove the link between parameters 1 and 6 and the fit. When there are two datagroups there are two separate model objects created so to change the sixth parameter, which is the first parameter of the model for the second datagroup we do:" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 5, 179 | "metadata": {}, 180 | "outputs": [ 181 | { 182 | "name": "stdout", 183 | "output_type": "stream", 184 | "text": [ 185 | "\n", 186 | "Fit statistic : Chi-Squared 3.256708e+08 using 33 bins.\n", 187 | " Chi-Squared 4.084839e+06 using 33 bins.\n", 188 | "Total fit statistic 3.297556e+08 with 60 d.o.f.\n", 189 | "\n", 190 | "Test statistic : Chi-Squared 3.297556e+08 using 66 bins.\n", 191 | " Null hypothesis probability of 0.000000e+00 with 60 degrees of freedom\n", 192 | " Current data and model not fit yet.\n", 193 | " Parameters\n", 194 | "Chi-Squared |beta|/N Lvl 1:nH 2:cutoffE 3:foldE 4:PhoIndex 5:norm 6:nH\n", 195 | "220543 9867.56 -3 0.333148 14.2798 36.6028 0.147414 0.00411629 0.283885\n", 196 | "215947 201943 -4 0.128858 13.1325 14.8783 0.00259899 0.00341326 0.0366783\n", 197 | "215135 171911 -5 0.368941 14.8072 7.49843 0.0640761 0.00381547 0.00600141\n", 198 | "214490 644803 -6 0.441643 14.5379 8.82389 0.0643614 0.00386068 0.00252599\n", 199 | "214432 468127 -7 0.485919 14.5043 9.02904 0.0669875 0.00388596 0.000811596\n", 200 | "214429 456922 -2 0.510309 14.4829 8.96366 0.0679087 0.00389913 0.000388265\n", 201 | "214404 463354 -3 0.514668 14.4459 9.13292 0.0667926 0.00389109 0.000175845\n", 202 | "214320 451243 -4 0.571311 14.4601 9.11420 0.0706216 0.00393704 7.03735e-05\n", 203 | "214298 428465 -1 0.586668 14.5286 9.08019 0.0723297 0.00394936 2.16957e-05\n", 204 | "214193 421731 -2 0.716931 14.8688 8.09433 0.0833144 0.00407428 9.80346e-06\n", 205 | "Number of trials exceeded: continue fitting? 214052 394059 0 0.757403 14.7708 8.38901 0.0825967 0.00409316 2.40852e-06\n", 206 | "213638 335202 -1 1.11498 14.5947 8.85045 0.0853738 0.00425318 2.99592e-07\n", 207 | "212904 85197.4 -2 2.09752 14.7079 9.38267 0.172575 0.00517626 1.05067e-07\n", 208 | "212806 219741 -3 4.10472 15.4754 9.83384 0.350441 0.00749112 1.94492e-08\n", 209 | "***Warning: Zero alpha-matrix diagonal element for parameter 6\n", 210 | " Parameter 6 is pegged at 1.94492e-08 due to zero or negative pivot element, likely\n", 211 | " caused by the fit being insensitive to the parameter.\n", 212 | "209758 552859 -2 6.51448 15.6778 10.0425 0.451960 0.0102006 1.94492e-08\n", 213 | "207240 269853 -2 10.3620 15.9862 10.4370 0.603439 0.0148987 1.94492e-08\n", 214 | "205214 291214 -2 17.5494 16.3449 11.1012 0.835406 0.0257588 1.94492e-08\n", 215 | "191984 324874 -1 23.3363 15.5371 11.0329 0.833163 0.0328918 1.94492e-08\n", 216 | "185862 71246 -1 30.2632 14.5910 11.2310 0.868496 0.0397037 1.94492e-08\n", 217 | "Number of trials exceeded: continue fitting? 177767 65291.1 -1 39.4296 13.3246 11.7797 0.908941 0.0494062 1.94492e-08\n", 218 | "164920 69446.3 -1 52.8504 11.2860 12.3169 0.943052 0.0642380 1.94492e-08\n", 219 | "138495 80667.9 -1 76.6503 7.08944 11.8128 0.928434 0.0906922 1.94492e-08\n", 220 | "125659 124599 0 80.1719 7.05271 11.2810 0.902787 0.100909 1.94492e-08\n", 221 | "120907 60996 -1 103.087 4.80632 6.79762 0.832274 0.141486 1.94492e-08\n", 222 | "90955.2 113861 -2 128.202 8.41987 5.95082 0.817197 0.160683 1.94492e-08\n", 223 | "85546.6 35356.6 -3 135.188 5.45293 6.06266 0.573823 0.122943 1.94492e-08\n", 224 | "84749.1 35401.1 -3 140.836 7.61059 5.85790 0.738242 0.145785 1.94492e-08\n", 225 | "84709.3 12048.3 -3 140.767 5.59164 5.65659 0.511520 0.114741 1.94492e-08\n", 226 | "84255.5 35235.5 -3 142.272 7.29392 5.75903 0.696373 0.138805 1.94492e-08\n", 227 | "Number of trials exceeded: continue fitting? 83193.5 19638.5 -2 140.908 6.11129 5.80183 0.603226 0.134340 1.94492e-08\n", 228 | "83069.3 3239.41 -3 141.654 6.84792 5.58914 0.627374 0.133392 1.94492e-08\n", 229 | "82939.2 437.368 -2 140.578 6.24236 5.61527 0.579925 0.129147 1.94492e-08\n", 230 | "82909.3 1141.99 -3 140.975 6.63680 5.52915 0.597574 0.129213 1.94492e-08\n", 231 | "82870.3 80.4941 -2 140.432 6.34338 5.53871 0.573720 0.127180 1.94492e-08\n", 232 | "82860.4 260.727 -3 140.616 6.49770 5.49369 0.577277 0.126430 1.94492e-08\n", 233 | "82855.3 31.242 -2 140.408 6.38373 5.49676 0.567694 0.125609 1.94492e-08\n", 234 | "82854.1 54.0641 -3 140.480 6.43266 5.47749 0.567343 0.125052 1.94492e-08\n", 235 | "82853.6 5.55634 -4 140.452 6.38186 5.46413 0.558930 0.123855 1.94492e-08\n", 236 | "82852.7 47.8308 -2 140.486 6.40922 5.46291 0.561266 0.124062 1.94492e-08\n", 237 | "Number of trials exceeded: continue fitting? 82852.4 14.8929 -3 140.471 6.40583 5.46869 0.562579 0.124368 1.94492e-08\n", 238 | "82852.4 2.82098 1 140.471 6.40583 5.46869 0.562579 0.124368 1.94492e-08\n", 239 | "***Warning: Zero alpha-matrix diagonal element for parameter 6\n", 240 | " Parameter 6 is pegged at 1.94492e-08 due to zero or negative pivot element, likely\n", 241 | " caused by the fit being insensitive to the parameter.\n", 242 | "82852.4 2.37912 0 140.470 6.40584 5.46869 0.562579 0.124368 1.94492e-08\n", 243 | "============================================================\n", 244 | " Variances and Principal Axes\n", 245 | " 1 2 3 4 5 \n", 246 | " 3.5982E-08| -0.0004 0.0169 0.0181 -0.2652 0.9639 \n", 247 | " 8.1972E-06| -0.0017 0.1112 0.2060 -0.9359 -0.2633 \n", 248 | " 5.8370E-04| -0.0238 0.3414 -0.9263 -0.1545 -0.0311 \n", 249 | " 2.5722E-03| 0.0224 -0.9327 -0.3146 -0.1730 -0.0253 \n", 250 | " 1.2403E-01| 0.9995 0.0293 -0.0147 -0.0015 -0.0002 \n", 251 | "------------------------------------------------------------\n", 252 | "\n", 253 | "============================================================\n", 254 | " Covariance Matrix\n", 255 | " 1 2 3 4 5 \n", 256 | " 1.239e-01 3.571e-03 -1.824e-03 -1.959e-04 -2.837e-05\n", 257 | " 3.571e-03 2.412e-03 5.172e-04 3.779e-04 5.358e-05\n", 258 | " -1.824e-03 5.172e-04 7.825e-04 2.247e-04 3.727e-05\n", 259 | " -1.959e-04 3.779e-04 2.247e-04 9.840e-05 1.613e-05\n", 260 | " -2.837e-05 5.358e-05 3.727e-05 1.613e-05 2.824e-06\n", 261 | "------------------------------------------------------------\n", 262 | "\n", 263 | "========================================================================\n", 264 | "Model phabs<1>*highecut<2>*powerlaw<3> Source No.: 1 Active/On\n", 265 | "Model Model Component Parameter Unit Value\n", 266 | " par comp\n", 267 | " Data group: 1\n", 268 | " 1 1 phabs nH 10^22 140.470 +/- 0.351989 \n", 269 | " 2 2 highecut cutoffE keV 6.40584 +/- 4.91132E-02 \n", 270 | " 3 2 highecut foldE keV 5.46869 +/- 2.79734E-02 \n", 271 | " 4 3 powerlaw PhoIndex 0.562579 +/- 9.91965E-03 \n", 272 | " 5 3 powerlaw norm 0.124368 +/- 1.68042E-03 \n", 273 | " Data group: 2\n", 274 | " 6 1 phabs nH 10^22 1.94492E-08 +/- -1.00000 \n", 275 | " 7 2 highecut cutoffE keV 6.40584 = p2\n", 276 | " 8 2 highecut foldE keV 5.46869 = p3\n", 277 | " 9 3 powerlaw PhoIndex 0.562579 = p4\n", 278 | " 10 3 powerlaw norm 0.124368 = p5\n", 279 | "________________________________________________________________________\n", 280 | "\n", 281 | "\n", 282 | "Fit statistic : Chi-Squared 51448.96 using 33 bins.\n", 283 | " Chi-Squared 31403.45 using 33 bins.\n", 284 | "Total fit statistic 82852.41 with 60 d.o.f.\n", 285 | "\n", 286 | "Test statistic : Chi-Squared 82852.41 using 66 bins.\n", 287 | " Null hypothesis probability of 0.00e+00 with 60 degrees of freedom\n" 288 | ] 289 | } 290 | ], 291 | "source": [ 292 | "m1 = AllModels(1)\n", 293 | "m2 = AllModels(2)\n", 294 | "m2(1).untie()\n", 295 | "Fit.perform()" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": 6, 301 | "metadata": {}, 302 | "outputs": [], 303 | "source": [ 304 | "Plot.device=\"/null\"\n", 305 | "Plot.xAxis=\"keV\"\n", 306 | "Plot(\"data resid\")\n", 307 | "energies = Plot.x()\n", 308 | "edeltas = Plot.xErr()\n", 309 | "rates = Plot.y(1,1)\n", 310 | "errors = Plot.yErr(1,1)\n", 311 | "rates2 = Plot.y(2,1)\n", 312 | "errors2 = Plot.yErr(2,1)\n", 313 | "foldedmodel = Plot.model()\n", 314 | "foldedmodel2 = Plot.model(2)\n", 315 | "dataLabels = Plot.labels(1)\n", 316 | "residLabels = Plot.labels(2)\n", 317 | "# note that for matplotlib step plots we need an x-axis array which includes the start and end value for each\n", 318 | "# bin and the y-axis has to be the same size with an extra value added equal to the value of the last bin\n", 319 | "nE = len(energies)\n", 320 | "stepenergies = list()\n", 321 | "for i in range(nE):\n", 322 | " stepenergies.append(energies[i] - edeltas[i])\n", 323 | "stepenergies.append(energies[-1]+edeltas[-1])\n", 324 | "foldedmodel.append(foldedmodel[-1])\n", 325 | "foldedmodel2.append(foldedmodel2[-1])\n", 326 | "resid = Plot.y(1,2)\n", 327 | "resid.append(resid[-1])\n", 328 | "resid2 = Plot.y(2,2)\n", 329 | "resid2.append(resid2[-1])" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": 7, 335 | "metadata": {}, 336 | "outputs": [ 337 | { 338 | "data": { 339 | "text/plain": [ 340 | "" 341 | ] 342 | }, 343 | "execution_count": 7, 344 | "metadata": {}, 345 | "output_type": "execute_result" 346 | }, 347 | { 348 | "data": { 349 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAEWCAYAAAB42tAoAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAArgklEQVR4nO3de7xVdZ3/8dcbEDU0khADEVHHSqfsqKTDLwryUlaWZmrKr7Lb0FQ6Mb9mMqtJx3LM6aZdtI4TaQUWlZbdLyTWOKSBnkSlslRSMZFQVBIR+Pz+WGvDOufs+1777Nv7+Xicx1m3vfZn77PP+uzv97u+368iAjMzs1JGtToAMzNrb04UZmZWlhOFmZmV5URhZmZlOVGYmVlZThRmZlaWE4WNOElXSPpoq+OolaQ5ku4rs/9Fku6U9LikEyuc6zxJXyuz/x5Jx9QZZ92PbYSkN0v6nyqP7cjPQK9yorC2JmmppLe3Oo4qnQ98LiJ2i4jvtDoYs7w4UZjlZ1/g9lYHYZY3JwprOkmHSrpZ0mOSvgHsktm3h6TvS3pI0sPp8tR03wXAi4HPpdU5n0u3XyLpXkmPSloh6cVlnvtVkm5Jj71X0nmZfdMlhaQzJP1Z0jpJH8zs3zWtInlY0h3AC8s8z5+A/YHvpbHuLGmKpGslrZf0R0n/WObxb5S0WtJfszGk+0ZJer+kP6X7F0uaUM1jizzPFZIulfSjNM4bJD1L0sXp6/ydpEMzxx+UluoekXS7pNdk9j0zfX2PSroJOGDIcz1X0s/S1/97SaeWi83alxOFNZWkscB3gK8CE4BvAq/LHDIK+DLJt/FpwBPA5wAi4oPAr4Az0+qcM9PH/AboS8+3CPimpF0obiPwJuAZwKuAdxZpP5gFPAc4GviwpIPS7eeSXPwOAF4OnFHqdUbEAcCfgVensT4JfB24D5gCnAz8p6Sjhj5W0sHAZcAb02OfCUzNHHIWcCIwO93/MPD5Kh9bzKnAh4CJwJPAMuDmdP1bwKfSc+8EfA/4KTApjWOhpOek5/k8sAmYDLw1/Sm8pnHAz0j+PpOA04BL03it00SEf/zTtB/gJcAaQJlt/wt8tMTxfcDDmfWlwNsrPMfDwAuqjOdi4NPp8nQggKmZ/TcBp6XLdwHHZfbNA+4rc+57gGPS5X2ArcDumf0XAleky+cBX0uXPwx8PXPcOGBz5lyrgKMz+ycDTwFjKj22SIxXAJdn1s8CVmXWnw88ki6/GPgLMCqz/6o09tFpDM/N7PtP4H/S5dcDvxry3F8Ezs3EUfQz4J/2+xlTMoOY5WMKcH+kV4fU6sKCpKcBnwaOA/ZIN+8uaXREbC12Qkn/CrwtPXcATyf5Nlzs2COBjwHPA8YCO5OUarL+kln+G7BbJvZ7i8VdhSnA+oh4bMjjZ5Q4dvvzRMRGSX/N7N8XuEbStsy2rcBeVTy2mAczy08UWR/0+iMi+7yrgb2BPUkSVan3Z1/gSEmPZLaNISlZWodx1ZM12wPA3pKU2TYts/xekmqfIyPi6SQlEIDC8YOGN07bI95HUn2yR0Q8A9iQOX6oRcC1wD4RMR74Qplji8W+T4m4K1kDTJC0+5DH31/pedLk+czM/nuBV0TEMzI/u0TE/VU8thFrgH0kZa8ThdfwELCF0u/PvcD1Q2LeLSLemVNsNoKcKKzZlpFcUP5Z0k6STgKOyOzfneRb7CNpA+25Qx7/IEkjcfb4LSQXqjGSPkxSoihld5Jv9pskHQHMrSH2xcA5aYP7VJJqmqpExL0kVWwXStpF0iEkpaBifSe+BRwvaVbapnM+g/83vwBcIGlfAEl7Sjqhysc24kaSEtb70r/dHODVJFVdW4GrgfMkPS1te8i24XwfeHba0L5T+vPCTPuPdRAnCmuqiNgMnAS8GVhPUnd9deaQi4FdgXXAr4EfDznFJcDJ6R05nwF+kh7zB5Kqjk0Mrv4Y6l3A+ZIeI6nPX1xD+P+RPsfdJA26tVabnE7SDrIGuIakfv7nQw+KiNuBd5OUfh4gaXPJduy7hKRU9NP0dfwaOLLKx9Yt/du9GngFyd/nUuBNEfG79JAzSaqp/kLS5vDlzGMfA15G0oi9Jj3mIpKqP+swGlx1bGZmNphLFGZmVpYThZmZleVEYWZmZTlRmJlZWV3Z4W7ixIkxffr0VodhZtZRVqxYsS4i9hy6vSsTxfTp01m+fHmrwzAz6yiSio4+4KonMzMry4nCzMzK6sqqp47W3w+LFjV+nrlzYd68xs9jZj3PJYpWW7YMLrww+Q1JkhgYaOycAwP5JBszM1yiGHn9/fC+9yXLW7bAxo079o0bB5s2waxZsHRpsm3ZsmR5zhyYObO655gzJ794zaznOVGMtEWL4PHHYbfdkkSRtWVLsn3NmuRiv2HDjtLFqFFwyCEwfvyOJGJmNgJc9dRsQ6uWICkxPPIIXHcd7LorjB6d/L7uumT7lCnJcRs27HjMtm2D183MRohLFM1QqPopViK4+27o60u2zZwJS5YMr1rKVjsdfTRs3gxjx8LChcOrn0pVTQ0MlK+CcmO3mVWp7kQh6eyIuCjPYLpONSWCmTNLtz2USiTlEtH48UnVVSEZFVN4jBOFmVWh6kQhKTvhi4A+kolILKu/f8fy+PHJBXzbtuT3+PGwfn1t5yuXSIolovHjk6qrcu0Ybuw2sxrUUqJ4NCLeXliRdFkT4ul8hdtb+/qSi/Yhh+y4gI8fn2yfW8tsnEXUUjVlZtagWhLFBUPWP5hnIF2lr29k7kwqVTVlZpajqhNFRNwNIGliRKyLiBrrUKwpylVNmZnloJ7bYxfkHoWZmbWteu56Uu5RWHMVu4XWt8+aWZXqSRSRexSWv3K30G7c6NtnzaxqLlF0u2K30E6b5ttnzaxq9SSKc3KPwvLnW2jNLCc1JQpJnweualIs1gy+hdbMGlRrieIPwMclTQYWA1dFxC35h2W5qnQLbT1DmZtZz6gpUUTEJcAlkvYFTgMWSNqVpJRxVUT8oQkxWjNUO3ChmfW8ugYFjIjVJOM8XSTpUJK+FR8GRucYm42EUgMX+vZZM0vVlSgkjQFeQVKqOBpYCpyXW1TWfOUau1euLD+Vqm+fNesptTZmHwucDrwSuAn4OjAvIjaWfWA36/T6/WKN3TNnDk4CQ1+jb5816ym1lijOARYB742Ih5sQT3vLzncN5ee87iTFGrvdhmFmqVobs48CUOINwP4Rcb6kacCzIuKmZgTZNrLzXUPpOa8bHUa8nXg6VrOeV++c2ZcCM0mqoQAeAz6fS0TtrjDfdbk5r7uh7n7p0uRn4cLBr3HhQpcmzHpMvVOhHhkRh0m6BSAiHpY0Nse4OkMvdGbrhddoZmXVmyiekjSadIBASXsC23KLqpP0wnwQvfAazaykehPFZ4BrgEmSLgBOBj6UW1TW/tzPwqxn1NvhbqGkFSR9KAScGBGrco3M2lelxnr3szDrKvV2uDs8IlYAv8tsOz4ivp9bZNa+5s1zPwuzHlJv1dPlkt4UEbcBSDodmA84UfQK97Mw6xn1JoqTgW9Jmgu8GHgT8LLcorLO4X4WZl2vrn4UEXEXyThPVwOvA14WEb5C9BL3szDrGbWO9bSSwXNmTyAZMfZGSUTEIXkGZx3A/SzMul6tVU/HNyUK62zuZ2HW1Wod62l1swIxM7P2VG9jtll5lTrkgTvlmXUIJwrLXzWj57pTnlnHcKKw/A3tkAfulGfWwepOFJLOjoiL6njcApJG8bUR8bx02wTgG8B04B7g1HREWgGXkMyo9zfgzRFxc70x2wjKJoING+DWW5N+Fu6UZ9Zxqu5HIWlx5uebwNvrfM4rgOOGbHs/sCQiDgSWpOuQzMt9YPozD7iszue0VtqwIUkS4E55Zh2olhLFoxGxPTlIquuiHRG/lDR9yOYTgDnp8pXAUuDsdPtXIiKAX0t6hqTJEfFAPc9tI2jp0h3Ly5bB0UfD5s0wdmzSKe+cc1oWmpnVppZEccGQ9Q/mGMdemYv/X4C90uW9gXszx92XbhuWKCTNIyl1MG3atBxDs4a5U55ZR6s6UUTE3QCSJkbEuohY34yAIiIkReUjhz2uH+gHmDFjRs2PtyZzpzyzjlVPY/YC4DU5x/FgoUpJ0mRgbbr9fmCfzHFT023WDbJ9LTZsSH7Gj09+wP0szNpEPYlCuUcB1wJnAB9Lf383s/1MSV8HjgQ2uH2iS8ydmySKgQHYsgU2btyxb9w42LQpWXaiMGu5ekaPbahaR9JVwDLgOZLuk/Q2kgRxrKQ7gWPSdYAfAncBfwQuB97VyHNbG5k3L7k9tq8PJk0avG/SJNhtt1ZEZWZFjHiJIiJOL7Hr6CLHBvDuRp7P2ljhzijfFWXW1upJFP4PtnxVc1fU0J7dZjZiak4UEXGbpFOAH0fEY5I+BBwGfNS9pq1uxe6KKjR2F+vZPX784L4aZtY0dc1wB/x7miRmkbQpfAn3mra8Pf54kixWrRrcs3vVqmR7f38rozPrGfUmiq3p71cB/RHxA2BsPiGZkdwVNWtW0th90EFJSQKS3wcdlCwvWtSy8Mx6Sb2DAt4v6YvAscBFknam/qRjNtzQEWg9+qxZy9SbKE4lGdjvExHxSNpJ7t/yC6tF5s/fMU9CMQMDHvG0VSr17HZjt1nT1JUoIuJvwNWZ9QcoMv5S1+nrq25SHhsZ2cbuQoJ3Y7dZ7jxxUdbFFw9e97fUzpAdtrwwjHlhGBAza5gTxVDZsYd8S2ZnGD8++RsV/laFJNHf7yFAzHJQVwO0pFMk7Z4uf0jS1ZIOyze0FvNkO+1t7twd7UXjxyeJfL/9diT0gYHBd0UtWwYXXpj8NrOaKBklo8YHSbdGxCFpP4qPAh8HPhwRR+YdYD1mzJgRy5cvb+wkQ4eVWLLE1U+dZM6cHTcflGrDAJcQzTIkrYiIGUO3ux9FKYVhJT7yESeJTlesDcPMquZ+FOV4sp3O1teXlBiKDTro8aTMquZ+FNb9yg066JsXzCqqN1GcGxFnF1bSmenmAz/NJSqzPGRn0Cv4yU8Gr69ZA1OmFL95wbfYmgH1VxcdW2TbKxoJxCxX2buiShkYSJLE0qVJddSuu8Lo0cnvhQuHlyZ855T1qJpKFJLeSTLL3P6Sbs3s2h24Ic/AzBoydKyoYrKljVLVU66aMqu56mkR8CPgQuD9me2PRcT63KIya4VyNy+4asp6WE2JIiI2ABuAUtOZmnWWYu0YWXPnJiWTau6c8l1T1qXqasxOb4d9HTA9e46IOD+fsMxGQKUBHgud9ObNc9WU9bR673r6LknJYgXwZH7hmI2gSu0YQ0sarpqyHlVvopgaEcflGolZJyqUGFw1ZV2s3kTxv5KeHxErc43GrN1U24ZRb9UUuHrK2l69iWIW8BZJd5FUPQmIiDgkt8jMWq2WNgxw1ZR1rXpHj9232PaIWN1wRDnIZfRYs0oKpYVqSgTVjkbs6ilroVKjx9ZbojijxHbf9WRWjMebsg5Wb6LYmFneBTgeWNV4OGYdpto2DKg8GnE11VMucVgL1JUoIuKT2XVJnwB+UuJws+5UaxtGKZXunHKJw1osrzmznwZMzelcZp2h1n4YlZSrngKXOKxl6u2ZvRIotIKPBvbE7RNmw1WqmoLK1VMucViL1VuiOD6zvAV4MCK25BCPWfeoVDUF1VdPgUsc1jJ13R4LIOkFwIvT1V9GxK3ljh9Jvj3WOsacOUmyKDd3RrbEUU6pW3Bd4rAqlbo9tq6JiyS9B1gITEp/Fko6q7EQrV15vp4mqjTB0sAALFpU3bkKJY6PfKR4P41iJY5i/Ae3IertcHcrMDMiNqbr44Bl7dIz2yWK2hSrjajlS6hrM5poJEsc4D94j8u7w52ArZn1rek26xDVDEFU2F+s2tu1GSOkUjvH9dcnP+VKHZXGo8rK4w/uRNJ16k0UXwZulHRNun4isCCXiCx35f5vS10XarnRppohjHztqFOlW3D7+8sniWrGoxp6ka/nD+5E0tUaacw+jGRwQIBfRcQtuUXVoE6qeqr0P1Pv/mr/b4vVRqxcOfjas2HDjutBIQmUmvitWbUZzdhf6Rqbh2prhZqmnqqrcm9mpT/4n/8Md9+94/j99oNp03asO5G0tVJVT/W2UVwJvCciHknX9wA+GRFvbTTQPIxkoqjnAlVLtU8j+6H0/225/8tK15brr09+z569I46hiWTNGpgypXwMjbzOjRth7dpk/5YtyXrBuHEwJlNWLrW/0JZb7nVk1bq/mvepmudoKNlUyoZDgywlG0QrEgk4mYyAvBPFLRFxaKVtrZJXoih3kYfGL+SV/mca2V9LiWGoQpIo1c5QTW1H9vH1XDvGjNmRCDZtgicz8yjuvPOO9fHji+/fZZcd6+X2T5qUJLRmJO1aklmpYwrrzUpmx6/pZ64WMWXy8GO3qzaZlAui2iJopQ994fy1Now5sVQl70TxW2BORDycrk8Aro+I5zccaQ4aSRTVftuH+i/klS6gBY3uzx5XS4kBGvsWW+z85S5gxd7rQtX67Nml/xaVrj3Z119qf7XXp2bvL3VMNmHWW3Iqt39oIoLiyeSYtTu+Gfx2y8Es39LHjDEDvGDMHQBM2ovtyWbZhoNZuqGPOeMHmDn+jmGJZuWaCfx1XfDMieL5U9Yn+6r5Y9aSTLKq+WeG5ieaDkhWeSeKNwEfAL6ZbjoFuCAivtpQlKWf7zjgEpLhQv47Ij5W7vg8EkW1VTaNXshbUfdeqcTQqHrq/itVuYxEG0Yzk3a1n4VGvmzXsz+biKCxZDN+fPH9b9vWzymbkw/EbXEw87d9iqfYiZ14iotH/T/+adtlAAyMTxLJmicnsOWpYMxOYsrO6xnqaVs2sP/G2xDbCEZx17jn8bcx45m0+V6mjP3rsOPZtIl48slkdjVAQ4ucBYXi5VAbNrD1t7eh2EpoNKNf8LzaJ52q9hxl/ilX9i/jr99eyjNfN4fnz2tOosk1UaQnPBg4Kl39RUTc0UB85Z5nNPAH4FjgPuA3wOnlni+Pqqe85pnJ+0tENRfhamoKWt7I2oZa0aBeyzHNSlbZ6tRGk0091YDvGFU+kTxPg//Vb4uDuWrbqbyIG7iBF3H6qMU8d1tyzJjRw9/Th7ZN4OXxY3ZiM08xlp/oOPYcNTgBzdqa/NOs4PBhjw+CPn7LGLbyFKP5LS9ANfYGaPQcD7AXR3EdY9nMZsbyC17KZB4seuzjfbOYfcvFNcVXkHuiGCmSZgLnRcTL0/VzACLiwlKPqTdRzJ+/o8oDqmt8HGn1tD1a9+jWklUttUrVlIyyNm2CQ59cxhyWspQ53LLzzGEFijM270hWQ92w9UjO4rPbE81nOYsXjb6x+JOVUO05dt36eNHH388UXskPtyeaH/FK9mZN0WN7NVGcDBwXEW9P198IHBkRZw45bh4wD2DatGmHr169uubnGpoo2pWTgDVTK0tWjVTRlXs9tRxf7PHnzFnGi55ayg07zeHCpTNrrh1o9Bwr+5dxwDuO3p5o/vTFJU2pfur6RJHVSf0ozGywRqvo8jg+78fncY6ObKMYKSNZ9WRm1styHT12hP0GOFDSfpLGAqcB17Y4JjOzntH2JQoASa8ELia5PXZBRFxQ4fiHgNobKTrbRGBdq4NoU35vSvN7U1yvvi/7RsSeQzd2RKKwyiQtL1ZkNL835fi9Kc7vy2CdUPVkZmYt5ERhZmZlOVF0j/5WB9DG/N6U5vemOL8vGW6jMDOzslyiMDOzspwozMysLCeKLiDpHkkrJQ1I6uku6ZIWSFor6bbMtgmSfibpzvT3Hq2MsRVKvC/nSbo//dwMpP2Veo6kfSRdJ+kOSbdLek+6vec/NwVOFN3jpRHR53u/uQI4bsi29wNLIuJAYEm63muuYPj7AvDp9HPTFxE/HOGY2sUW4L0RcTDwD8C702kU/LlJOVFYV4mIXwJDZ7s5AbgyXb4SOHEkY2oHJd4XAyLigYi4OV1+DFgF7I0/N9s5UXSHAH4qaUU63LoNtldEPJAu/wXYq5XBtJkzJd2aVk31bNVKgaTpwKHAjfhzs50TRXeYFRGHAa8gKTa/pNUBtatI7gf3PeGJy4ADgD7gAeCTLY2mxSTtBnwbmB8Rj2b39frnxomiC0TE/envtcA1wBGtjajtPChpMkD6u8RcaL0lIh6MiK0RsQ24nB7+3EjaiSRJLIyIq9PN/tyknCg6nKRxknYvLAMvA24r/6iecy1wRrp8BvDdFsbSNgoXwdRr6dHPjSQBXwJWRcSnMrv8uUm5Z3aHk7Q/SSkCYAywqNIw7N1M0lXAHJJhoh8EzgW+AywGppEMP39qRPRUw26J92UOSbVTAPcA78jUyfcMSbOAXwErgW3p5g+QtFP09OemwInCzMzKctWTmZmV5URhZmZlOVGYmVlZY1odQDNMnDgxpk+f3uowzMw6yooVK9YVmzO7KxPF9OnTWb68p8fGMzOrmaTVxba76snMzMrqyhKF2Yjo74dFi8ofM3cuzPPwW9bZnCjM6rVoEQwMQF9f8f3XX5/8OJlYh3OiMGtEXx8sXVp8XzUljmqSiROJtZgThVkplS705UoTkFzcK13gq3mOwrnMWsSJwqyUSlVLfX3Jt/1GVEomc+YkMcyZU/oYlzisyZwozMopV7U0EiolIpc4bATUnCgknR0RFzUjGLMR1WjV0kiopsRh1mQVE4WkxdlVkmGJnSis841E1dJIcNWUNVk1JYpHI+LthRVJlzUjEEkLgOOBtRHxvHTbBOAbwHSS8fJPjYiHm/H81qNaXbXUKFdN2QioJlEMnQTng80IBLgC+Bzwlcy29wNLIuJjkt6frp/dpOc36zyumrIRUDFRRMTdAJImRsS6Zs3wFBG/lDR9yOYTSGbhArgSWIoThVltXDVlDaplrKcFTYuitL0yUzP+Bdir1IGS5klaLmn5Qw89NDLRmbW7uXPLN8gPDFTuFGg9r5a7ntS0KKoQESGp5LytEdEP9APMmDGjY+d39fBBlitXTVkOakkUrbj4PihpckQ8IGkysLYFMeSqUiK4/vrk9+zZpfd7+CAzG0ntXqK4FjgD+Fj6+7stiCFXle7InD27/EW+mhKHb3Sh+jeq1f0k2kGlNgzwN48eV0uiOKdpUQCSriJpuJ4o6T7gXJIEsVjS24DVwKnNjCEP1fbhqveOzGqGD3JtApUzMnROP4lmqub1+5tHz6sqUUj6PHBVMwOJiNNL7Dq6mc+bt3bpw+UbXej8PhIjwd88rArVlij+AHw8bSdYDFwVEbc0L6z2VEtthocHsq7ibx49rapEERGXAJdI2hc4DVggaVeSUsZVEfGHJsbYNjqlNiOPAUkr8XWhh/ibR8+raVDAiFhNMs7TRZIOJelb8WFgdBNia0utLi3kodFE5utCj/FQ6D2vpkQhaQzwCpJSxdEkPaXPyz0qa6pqqqXLcZW1DeISR9ertjH7WOB04JXATcDXgXkRsbGJsZlZJ3Cnvq5XbYniHGAR8F6P3mpmNXPVVEertjH7KAAl3gDsHxHnS5oGPCsibmpmkNZ+Wv5/3wmTDlnCVVMdr9YZ7i4FtgFHAecDjwHfBl6Yc1zWxtri/75dOqxYZa6a6ni1JoojI+IwSbcARMTDksY2IS5rY23zf98Nt6BZwsOItLVaE8VTkkaTDhAoaU+SEkZXmD9/x7fhYlybUT3/31vVPIxI26s1UXwGuAaYJOkC4GTgQ7lH1aZcm1Ed/99bTaodRqTlDWO9q9YOdwslrSDpQyHgxIhY1ZTIWuDii3M4iSeU8PBBlr+2aBjrXbV2uDs8IlYAv8tsOz4ivp97ZJ2qUiOrP9Db+QuiVa1tGsZ6U61VT5dLelNE3AYg6XRgPuBEkVWukdUfaMBfEK0JPIBZ09SaKE4GviVpLvBi4E3Ay3KPyrqevyBarjyAWVPV2kZxl6TTgO8AfwZeFhFPNCMwM7OqeQCzpqp2rKeVDJ4zewLJiLE3SiIiDmlGcNa7jl/TzzFrFyVzHhbje5Utb41WXUHXVl9VW6I4vqlRmA1xzNpF7LdhgIGBvhJH9PHo1Lm8ZCSDsu6Vx33vXVx9Ve1YT6ubHYhZ1qS94G76mN+3tOj+gQHouy8Z596sYY1WXUFXzwhWa2O22YiYMjn58c1j1jG6uEHdiaIV3IHArPvk0aCeRztJX19OvYd36IhEIek44BKSBvT/joiPtTik+rkDgZkV08bjA9WcKCSdHREXNSOYEs83Gvg8cCxwH/AbSddGxB0jFUOu3IHAzIrJo52kSSomCkmLs6tAHzBiiQI4AvhjRNyVxvN14ASgKYni9V9cNmzb8YdM5o0zp7P50i9w58X9w/bvufvOTNp9Z57aGmxecTP3TD2Q8zPnecM/7MurXzCFNY88wb98Y2DY4//xxftzzMF78aeHHmfTmkcBBj3+rKMOZNaBE7l9zQbO/97wl/2+457D4ftOYMXq9fzXj38/bP+HX30wfz9lPP9z5zo++4s7h+3/z5OezwF77sbP73iQy39117D9n359H1OesSvf++0avvbr4fc1XPaGw5kwbizfXH4v31px37D9V7zlCHYdO5qvLruH79/6wLD933jHTAD6f/knlqxam8Scvg//teAmrnzrEQB8Zsmd3PDHdQDcseZgHrlvHFMOeoJn77U7AH9e/zce3/TU9vNOO2Ids45/lItPOxSA//je7dyRnrdg/z3HceFJyd3d51x9K3c9NHh234OnPJ1zX/33AMz/+i08sGHToP2H7bsHZx/3XAD+6asrePhvmwftf9HfTeSfjz4QgDMW3MSmp7YO2n/0QZOY95IDgPKfvSc2b+XNXx4+P9jJh0/llBn7sH7jZt75tRXD9tfy2fvA1SuH7e/Fz17BLjuNLvrZK9jjaWP5whsPB+CiH/+Om1cPnvxz8vhdWvLZK7ymPFVTong0It5eWJF0We5RlLc3cG9m/T7gyKEHSZoHzAOYNm1aUwIZ/Y2rmH7fndwz9cCSx9wz9UBuOOLYpjy/7TDtiMI/7aii+x+5b1yycPyjRfebZf3y2t257tqJg7aNGiXmfCVZvv/hvdnwxKRB+8eMHsXvvpQs/3n9NB7fNHnQ/rFjRjHwhWT5nr9O529Pbhm0f9nY0Sz7TLJ817r92bR58JeIG3cew3WfTJb/uPbv2Lxl8IwOv9llJ36UVsL/4cFns2Vrsn/+qtybKFBElD9A2i8i7s6sT4iI9fmGUfb5TwaOKyQrSW8kmUDpzFKPmTFjRixfvjz/YArVQs2cLGcknqMTNPg++G3sHNUMuNxs11+f/J49u7Vx5KGRtmxJKyJixtDtFUsUhSQhaWJErBvJJJG6H9gnsz413WZmbaDRC307XKRnz/bNhuXU0pi9AHhNswIp4zfAgZL2I0kQpwHte3uAWZeplAgavdD7It3+akkUaloUZUTEFklnAj8huT12QUTc3opYrLN4OtbKqikNVEoEvtB3v1oSRfnGjCaKiB8CP2zV81vn6ZXpWEei2seJwNq+RGFWj26ZjtXVPtYOakkU5zQtCus9la6AIzSMeKtHU2k0EfhCbyOh6kQREbdJOgX4cUQ8JulDwGHARyPi5qZFaN2p0tzifX1NH9Kg0umvvz75KXchL3eRdv2/dYtah/D494j4pqRZwDHAx4HLKNIBzqyicnOLj4BK1VPVfNsvl0hc/2/dotZEUeg6+CqgPyJ+IOmjOcdk1hYaTSROAtYtak0U90v6IskAfRdJ2plSYyiYdbk2HsPNLFe1XuRPJenP8PKIeIRk7ux/yzsoMzNrHzWVKCLib8DVmfUHgOFDMpqZWddwtZGZmZXVETPc2Qir5r5Ot9Ka9YyaShSSTpG0e7r8IUlXSzqsOaFZyxT6OJQyMND6caHNbMS4H4UVV66PQyeMfWFmuam1jWJYPwpgbL4hmZlZO3E/iqz58ytXuYzA+EMtH4CoGp0Qo5nlotZEcSpwHPCJiHhE0mR6qR/FCIw/VPH87TA2difEaGa5qThn9qCDpYsi4uxK21qtaXNmt4NOmLd7zpzKpa/Cfk9qbdY2Ss2ZXWu10bFFtr2ivpCsa82dW7mKbiRKZ2aWi6qqniS9E3gXsL+kWzO7dgduaEZg1sE8CJJZV6m2jWIR8CPgQuD9me2PRcT63KMyM7O2UVWiiIgNwAbg9OaGY2Zm7aamu57S22FfB0zPPjYizs83LDMzaxe1NmZ/FzgB2AJszPw0JB0a5HZJ2yTNGLLvHEl/lPR7SS9v9LnMzKw2tfajmBoRxzUhjtuAk4AvZjdKOhg4Dfh7YArwc0nPjoitw09hZmbNUGuJ4n8lPT/vICJiVUT8vsiuE4CvR8STEXE38EfgiLyf38zMSqs1UcwCbk6rgW6VtHLI7bJ52xu4N7N+X7ptGEnzJC2XtPyhhx5qYkhmZr2l1qqnujvXSfo58Kwiuz4YEd+t97wFEdEP9EPSM7vR85mZWaLWRHFGie0V73qKiGNqfC6A+4F9MutT021mZjZCaq16yt7ptJWkhDE955iyrgVOk7SzpP2AA4Gbmvh8ZmY2RE0lioj4ZHZd0ieAnzQahKTXAp8F9gR+IGkgIl4eEbdLWgzcQXJL7rt9x5OZ2chqdM7sp5FUBzUkIq4Brimx7wLggkafw8zM6lNrz+yVQKGheDRJCcC9ss3MulitJYrjM8tbgAcjYkuO8ZiZWZuptY1itaQXAC9ON/0SaGY/Cium0jSkUH4q0v5+WLSo/PlHYspXM+sINd31JOk9wEJgUvqzUNJZzQjMSqhmUqCBgfKJYNGi8nODe1IhM8uodSrUW4GZEbExXR8HLIuIQ5oUX126eirUalSaynQkplM1s46T11SoIuk/UbA13WZmZl2q1sbsLwM3SircynoisCDXiMzMrK3U2pj9KUlLSQYHBHhLRNySe1RmZtY2au1HcSXwnoi4OV3fQ9KCiHhrU6IzM7OWq7WN4pCIeKSwEhEPA4fmGpGZmbWVWhPFKEl7FFYkTaDxYUDMzKyN1XqR/ySwTNI30/VT8DhMZmZdrdbG7K9IWg4clW46KSLuyD8sMzNrFzVXG6WJwcmh3ZUb5sNDdJhZDdy+0I0qDb/hITrMrAZOFN1o3rzSAwKamdWo1ruezMysxzhRmJlZWU4UZmZWVk3DjHcKSQ8Bq1sdxwibCKxrdRBtyu9NaX5viuvV92XfiNhz6MauTBS9SNLyYuPIm9+bcvzeFOf3ZTBXPZmZWVlOFGZmVpYTRffob3UAbczvTWl+b4rz+5LhNgozMyvLJQozMyvLicLMzMpyougCku6RtFLSQDoMfM+StEDSWkm3ZbZNkPQzSXemv/cod45uVOJ9OU/S/ennZkDSK1sZY6tI2kfSdZLukHS7pPek23v+c1PgRNE9XhoRfb73myuA44Zsez+wJCIOBJak673mCoa/LwCfTj83fRHxwxGOqV1sAd4bEQcD/wC8W9LB+HOznROFdZWI+CWwfsjmE4Ar0+UrgRNHMqZ2UOJ9MSAiHoiIm9Plx4BVwN74c7OdE0V3COCnklZI8vjiw+0VEQ+ky38B9mplMG3mTEm3plVTPVu1UiBpOnAocCP+3GznRNEdZkXEYcArSIrNL2l1QO0qkvvBfU944jLgAKAPeAD4ZEujaTFJuwHfBuZHxKPZfb3+uXGi6AIRcX/6ey1wDXBEayNqOw9KmgyQ/l7b4njaQkQ8GBFbI2IbcDk9/LmRtBNJklgYEVenm/25STlRdDhJ4yTtXlgGXgbcVv5RPeda4Ix0+Qzguy2MpW0ULoKp19KjnxtJAr4ErIqIT2V2+XOTcs/sDidpf5JSBCRT2y6KiAtaGFJLSboKmEMyTPSDwLnAd4DFwDSS4edPjYieatgt8b7MIal2CuAe4B2ZOvmeIWkW8CtgJbAt3fwBknaKnv7cFDhRmJlZWa56MjOzspwozMysLCcKMzMry4nCzMzKcqIwM7OynCis50jamhkxdUBSWwz2psQvJD1d0vTsSK8VHjdb0rIh28ZIelDSFEmfkHRUc6K2XjCm1QGYtcATEdGX5wkljYmILQ2e5pXAbyPiUUkTanjcr4CpkvaNiNXptmOA2yNijaTPkvS8/kWD8VmPconCLJXO6/Efkm5O5/d4brp9XDpo3k2SbpF0Qrr9zZKulfQLYImkp0lanM5rcI2kGyXNkPRWSRdnnucfJX26SAj/lyK9fyXtnz7vCyUdIOnH6QCQv5L03HQIjsXAaZmHnQZcBZAmj2dKelZOb5X1GCcK60W7Dql6en1m37p0gMXLgH9Nt30Q+EVEHAG8FPh4OlwKwGHAyRExG3gX8HA6r8G/A4enxywGXp2OJwTwFmBBkbheBKzIbpD0HJIxiN4cEb8B+oGzIuLwNL5L00OvIk0UknYmKZ18O3Oqm9Pzm9XMVU/Wi8pVPRUGhFsBnJQuvwx4jaRC4tiFZFgHgJ9lhnWYBVwCEBG3Sbo1XX48LXUcL2kVsFNErCzy3BPS+RAK9iQpYZwUEXeko5v+H+CbyfBEAOycPsdySbulieUg4MYhw02sBaaUeM1mZTlRmA32ZPp7Kzv+PwS8LiJ+nz1Q0pHAxirP+98k4wf9DvhyiWO2SBqVViUBbAD+TJKA7iCpAXikTJIrlCoOSpezdgGeqDJWs0Fc9WRW2U+As9JRRpF0aInjbgBOTY85GHh+YUdE3AjsA8xl+EW84PfA/pn1zSSjur5J0tx0joS7JZ2SPockvSBz/FXAG4CjGN7W8Wx6dHRYa5wThfWioW0UH6tw/EeAnYBbJd2erhdzKbCnpDuAjwK3k5QKChYDN0TEwyUe/wOSEV23i4iNwPHAv0h6DUmD99sk/TY9/wmZY1eRlHB+kT4O2D7Xwt8Byyu8TrOiPHqsWU4kjSZpf9gk6QDg58BzImJzuv/7wKcjYkmJx08GvhIRx+Yc12uBwyLi3/M8r/UOt1GY5edpwHXpN3gB74qIzZKeAdxE0keiaJIAiIgHJF0u6elDp+Js0Bh6fJpTa4xLFGZmVpbbKMzMrCwnCjMzK8uJwszMynKiMDOzspwozMysrP8P2blHgWMeNkgAAAAASUVORK5CYII=\n", 350 | "text/plain": [ 351 | "
" 352 | ] 353 | }, 354 | "metadata": { 355 | "needs_background": "light" 356 | }, 357 | "output_type": "display_data" 358 | } 359 | ], 360 | "source": [ 361 | "plt.subplot(211)\n", 362 | "plt.ylabel(dataLabels[1])\n", 363 | "plt.title(dataLabels[2])\n", 364 | "plt.errorbar(energies,rates,xerr=edeltas,yerr=errors,fmt='.',color='b')\n", 365 | "plt.errorbar(energies,rates2,xerr=edeltas,yerr=errors2,fmt='.',color='r')\n", 366 | "plt.step(stepenergies,foldedmodel,where='post',color='b')\n", 367 | "plt.step(stepenergies,foldedmodel2,where='post',color='r')\n", 368 | "plt.subplot(212)\n", 369 | "plt.xlabel(residLabels[0])\n", 370 | "plt.ylabel(residLabels[1])\n", 371 | "plt.step(stepenergies,resid,where='post',color='b')\n", 372 | "plt.step(stepenergies,resid2,where='post',color='r')\n", 373 | "plt.hlines(0.0,stepenergies[0],stepenergies[-1],linestyles='dashed')" 374 | ] 375 | }, 376 | { 377 | "cell_type": "markdown", 378 | "metadata": {}, 379 | "source": [ 380 | "Clearly our assumption that only a change in absorption can account for the spectral variation before and after eclipse is clearly wrong. Perhaps scattering also plays a role in reducing the flux before eclipse. This could be modeled (simply at first) by allowing the normalization of the power law to be smaller before eclipse than after eclipse. To decouple tied parameters, we can change the parameter value in the second group to a value - any value - different from that in the first group (changing the value in the first group has the effect of changing both without decoupling)." 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": 8, 386 | "metadata": {}, 387 | "outputs": [ 388 | { 389 | "name": "stdout", 390 | "output_type": "stream", 391 | "text": [ 392 | "\n", 393 | "Fit statistic : Chi-Squared 51448.96 using 33 bins.\n", 394 | " Chi-Squared 9.949616e+06 using 33 bins.\n", 395 | "Total fit statistic 1.000107e+07 with 59 d.o.f.\n", 396 | "\n", 397 | "Test statistic : Chi-Squared 1.000107e+07 using 66 bins.\n", 398 | " Null hypothesis probability of 0.000000e+00 with 59 degrees of freedom\n", 399 | " Current data and model not fit yet.\n", 400 | " Parameters\n", 401 | "Chi-Squared |beta|/N Lvl 1:nH 2:cutoffE 3:foldE 4:PhoIndex 5:norm 6:nH 10:norm\n", 402 | "***Warning: Zero alpha-matrix diagonal element for parameter 6\n", 403 | " Parameter 6 is pegged at 1.94492e-08 due to zero or negative pivot element, likely\n", 404 | " caused by the fit being insensitive to the parameter.\n", 405 | "28403.7 173861 -3 37.3744 5.67197 8.29470 0.567248 0.0366093 1.94492e-08 0.120893\n", 406 | "21282.9 140465 -4 30.9428 5.14085 9.36123 0.510361 0.0227609 1.94492e-08 0.111853\n", 407 | "20084.6 93537.7 -3 29.4438 3.69099 8.19123 0.345370 0.0208368 1.94492e-08 0.0937947\n", 408 | "18713.6 53644.7 -2 26.7473 2.98087 8.12373 0.292166 0.0202251 1.94492e-08 0.0956424\n", 409 | "18589.2 2023.14 -2 25.4560 2.85357 7.94011 0.264508 0.0192985 1.94492e-08 0.0934280\n", 410 | "18522.7 1759.82 -2 24.6101 2.72212 7.82086 0.240585 0.0186062 1.94492e-08 0.0914817\n", 411 | "18505.2 1160.36 -3 23.6803 2.18058 7.31869 0.150112 0.0169913 1.94492e-08 0.0853591\n", 412 | "18421.9 20159.6 -4 23.2816 2.28459 7.29900 0.141862 0.0165769 1.94492e-08 0.0839997\n", 413 | "18419.5 498.919 -5 23.0436 2.18316 7.27728 0.136536 0.0165993 1.94492e-08 0.0844377\n", 414 | "Number of trials exceeded: continue fitting? 18418.8 113.228 -6 22.9231 2.23879 7.29215 0.139137 0.0164971 1.94492e-08 0.0840927\n", 415 | "18418.4 102.782 -7 22.8251 2.17674 7.28009 0.136214 0.0165320 1.94492e-08 0.0844125\n", 416 | "18418.4 47.6225 -8 22.7868 2.23695 7.29323 0.138827 0.0164480 1.94492e-08 0.0840383\n", 417 | "18418.2 75.1688 -9 22.7378 2.16879 7.27940 0.135716 0.0165080 1.94492e-08 0.0844170\n", 418 | "18418.2 57.0657 -3 22.7264 2.21083 7.28770 0.137469 0.0164536 1.94492e-08 0.0841571\n", 419 | "18418.1 24.5332 -3 22.7079 2.18439 7.28445 0.136629 0.0164854 1.94492e-08 0.0843439\n", 420 | "18418.1 16.3983 -3 22.7047 2.20490 7.28788 0.137394 0.0164577 1.94492e-08 0.0842082\n", 421 | "18418.1 3.17486 -2 22.6987 2.19951 7.28763 0.137275 0.0164644 1.94492e-08 0.0842500\n", 422 | "18418.1 10.0775 2 22.6987 2.19951 7.28763 0.137275 0.0164644 1.94492e-08 0.0842500\n", 423 | "***Warning: Zero alpha-matrix diagonal element for parameter 6\n", 424 | " Parameter 6 is pegged at 1.94492e-08 due to zero or negative pivot element, likely\n", 425 | " caused by the fit being insensitive to the parameter.\n", 426 | "18418.1 10.0125 3 22.6987 2.19951 7.28763 0.137275 0.0164644 1.94492e-08 0.0842500\n", 427 | "======================================================================\n", 428 | " Variances and Principal Axes\n", 429 | " 1 2 3 4 5 10 \n", 430 | " 1.6950E-09| 0.0003 -0.0023 -0.0023 0.0359 -0.9994 -0.0005 \n", 431 | " 2.2525E-08| 0.0000 0.0111 0.0139 -0.1852 -0.0072 0.9825 \n", 432 | " 6.9749E-06| -0.0056 -0.0077 -0.1624 0.9685 0.0351 0.1852 \n", 433 | " 2.7695E-03| -0.0005 -0.2333 0.9597 0.1554 0.0039 0.0183 \n", 434 | " 2.2852E-02| 0.4732 -0.8566 -0.2018 -0.0389 0.0011 0.0052 \n", 435 | " 4.1543E-02| 0.8809 0.4600 0.1079 0.0272 -0.0001 -0.0016 \n", 436 | "----------------------------------------------------------------------\n", 437 | "\n", 438 | "========================================================================\n", 439 | " Covariance Matrix\n", 440 | " 1 2 3 4 5 6 \n", 441 | " 3.736e-02 7.570e-03 1.766e-03 5.729e-04 1.046e-05 -2.535e-06\n", 442 | " 7.570e-03 2.571e-02 5.392e-03 1.181e-03 -2.587e-05 -1.439e-04\n", 443 | " 1.766e-03 5.392e-03 3.965e-03 7.133e-04 4.823e-06 1.748e-05\n", 444 | " 5.729e-04 1.181e-03 7.133e-04 1.388e-04 8.394e-07 2.723e-06\n", 445 | " 1.046e-05 -2.587e-05 4.823e-06 8.394e-07 8.228e-08 3.820e-07\n", 446 | " -2.535e-06 -1.439e-04 1.748e-05 2.723e-06 3.820e-07 1.914e-06\n", 447 | "------------------------------------------------------------------------\n", 448 | "\n", 449 | "========================================================================\n", 450 | "Model phabs<1>*highecut<2>*powerlaw<3> Source No.: 1 Active/On\n", 451 | "Model Model Component Parameter Unit Value\n", 452 | " par comp\n", 453 | " Data group: 1\n", 454 | " 1 1 phabs nH 10^22 22.6987 +/- 0.193277 \n", 455 | " 2 2 highecut cutoffE keV 2.19951 +/- 0.160342 \n", 456 | " 3 2 highecut foldE keV 7.28763 +/- 6.29704E-02 \n", 457 | " 4 3 powerlaw PhoIndex 0.137275 +/- 1.17796E-02 \n", 458 | " 5 3 powerlaw norm 1.64644E-02 +/- 2.86840E-04 \n", 459 | " Data group: 2\n", 460 | " 6 1 phabs nH 10^22 1.94492E-08 +/- -1.00000 \n", 461 | " 7 2 highecut cutoffE keV 2.19951 = p2\n", 462 | " 8 2 highecut foldE keV 7.28763 = p3\n", 463 | " 9 3 powerlaw PhoIndex 0.137275 = p4\n", 464 | " 10 3 powerlaw norm 8.42500E-02 +/- 1.38346E-03 \n", 465 | "________________________________________________________________________\n", 466 | "\n", 467 | "\n", 468 | "Fit statistic : Chi-Squared 16962.33 using 33 bins.\n", 469 | " Chi-Squared 1455.78 using 33 bins.\n", 470 | "Total fit statistic 18418.11 with 59 d.o.f.\n", 471 | "\n", 472 | "Test statistic : Chi-Squared 18418.11 using 66 bins.\n", 473 | " Null hypothesis probability of 0.00e+00 with 59 degrees of freedom\n" 474 | ] 475 | } 476 | ], 477 | "source": [ 478 | "m2.powerlaw.norm = 1.0\n", 479 | "Fit.perform()" 480 | ] 481 | }, 482 | { 483 | "cell_type": "code", 484 | "execution_count": 9, 485 | "metadata": {}, 486 | "outputs": [], 487 | "source": [ 488 | "Plot(\"data resid\")\n", 489 | "energies = Plot.x()\n", 490 | "edeltas = Plot.xErr()\n", 491 | "rates = Plot.y(1,1)\n", 492 | "errors = Plot.yErr(1,1)\n", 493 | "rates2 = Plot.y(2,1)\n", 494 | "errors2 = Plot.yErr(2,1)\n", 495 | "foldedmodel = Plot.model()\n", 496 | "foldedmodel2 = Plot.model(2)\n", 497 | "dataLabels = Plot.labels(1)\n", 498 | "residLabels = Plot.labels(2)\n", 499 | "# note that for matplotlib step plots we need an x-axis array which includes the start and end value for each\n", 500 | "# bin and the y-axis has to be the same size with an extra value added equal to the value of the last bin\n", 501 | "nE = len(energies)\n", 502 | "stepenergies = list()\n", 503 | "for i in range(nE):\n", 504 | " stepenergies.append(energies[i] - edeltas[i])\n", 505 | "stepenergies.append(energies[-1]+edeltas[-1])\n", 506 | "foldedmodel.append(foldedmodel[-1])\n", 507 | "foldedmodel2.append(foldedmodel2[-1])\n", 508 | "resid = Plot.y(1,2)\n", 509 | "resid.append(resid[-1])\n", 510 | "resid2 = Plot.y(2,2)\n", 511 | "resid2.append(resid2[-1])" 512 | ] 513 | }, 514 | { 515 | "cell_type": "code", 516 | "execution_count": 10, 517 | "metadata": {}, 518 | "outputs": [ 519 | { 520 | "data": { 521 | "text/plain": [ 522 | "" 523 | ] 524 | }, 525 | "execution_count": 10, 526 | "metadata": {}, 527 | "output_type": "execute_result" 528 | }, 529 | { 530 | "data": { 531 | "image/png": "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\n", 532 | "text/plain": [ 533 | "
" 534 | ] 535 | }, 536 | "metadata": { 537 | "needs_background": "light" 538 | }, 539 | "output_type": "display_data" 540 | } 541 | ], 542 | "source": [ 543 | "plt.subplot(211)\n", 544 | "plt.yscale('log')\n", 545 | "plt.ylabel(dataLabels[1])\n", 546 | "plt.title(dataLabels[2])\n", 547 | "plt.errorbar(energies,rates,xerr=edeltas,yerr=errors,fmt='.',color='b')\n", 548 | "plt.errorbar(energies,rates2,xerr=edeltas,yerr=errors2,fmt='.',color='r')\n", 549 | "plt.step(stepenergies,foldedmodel,where='post',color='b')\n", 550 | "plt.step(stepenergies,foldedmodel2,where='post',color='r')\n", 551 | "plt.subplot(212)\n", 552 | "plt.xlabel(residLabels[0])\n", 553 | "plt.ylabel(residLabels[1])\n", 554 | "plt.step(stepenergies,resid,where='post',color='b')\n", 555 | "plt.step(stepenergies,resid2,where='post',color='r')\n", 556 | "plt.hlines(0.0,stepenergies[0],stepenergies[-1],linestyles='dashed')" 557 | ] 558 | }, 559 | { 560 | "cell_type": "markdown", 561 | "metadata": {}, 562 | "source": [ 563 | "This decoupling improves the fit, but it still clearly not good. Indeed, this simple attempt to account for the spectral variability in terms of \"blanket\" cold absorption and scattering does not work. More sophisticated models, involving additional components and partial absorption, should be tried." 564 | ] 565 | } 566 | ], 567 | "metadata": { 568 | "kernelspec": { 569 | "display_name": "Python 3 (ipykernel)", 570 | "language": "python", 571 | "name": "python3" 572 | }, 573 | "language_info": { 574 | "codemirror_mode": { 575 | "name": "ipython", 576 | "version": 3 577 | }, 578 | "file_extension": ".py", 579 | "mimetype": "text/x-python", 580 | "name": "python", 581 | "nbconvert_exporter": "python", 582 | "pygments_lexer": "ipython3", 583 | "version": "3.12.6" 584 | } 585 | }, 586 | "nbformat": 4, 587 | "nbformat_minor": 4 588 | } 589 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/PyXspecWalkthrough3-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# older versions of Jupyter may need wurlitzer in order to redirect the C output to the notebook\n", 10 | "# %load_ext wurlitzer\n", 11 | "\n", 12 | "import IPython.display\n", 13 | "\n", 14 | "from xspec import *" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "##Multiple Models: a Background Modeling Example\n", 22 | "\n", 23 | "We now demonstrate how to fit multiple models, each with their own response, to the same dataset. There are several reasons why this may be useful, for instance:\n", 24 | "\n", 25 | " We are using data from a coded aperture mask. If there are multiple sources in the field they will all contribute to the spectrum from each detector. However, each source may have a different response due to its position.\n", 26 | " We are observing an extended source using a telescope whose PSF is large enough that the signal from different regions are mixed together. In this case we will want to analyze spectra from all regions of the source simultaneously with each spectrum having a contribution from the model in other regions.\n", 27 | " We wish to model the background spectrum that includes a particle component. The particle background will have a different response from the X-ray background because the particles come from all directions, not just down the telescope.\n", 28 | "\n", 29 | "We will demonstrate the third example here. Suppose we have a model for the background spectrum that requires a different response to that for the source spectrum. The spectra and corresponding response matrices were obtained from the HEASARC and are available from https://heasarc.gsfc.nasa.gov/docs/xanadu/xspec/walkthrough.tar.gz\n", 30 | "\n", 31 | "Read in the source and background spectra as separate files. \n" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "name": "stdout", 41 | "output_type": "stream", 42 | "text": [ 43 | "/Users/karnaud/Jupyter-notebooks/data\n", 44 | "\n", 45 | "2 spectra in use\n", 46 | " \n", 47 | "Spectral Data File: hisum.pha Spectrum 1\n", 48 | "Net count rate (cts/s) for Spectrum:1 1.371e+03 +/- 3.123e+00\n", 49 | " Assigned to Data Group 1 and Plot Group 1\n", 50 | " Noticed Channels: 1-48\n", 51 | " Telescope: GINGA Instrument: LAC Channel Type: PHA\n", 52 | " Exposure Time: 1 sec\n", 53 | " Using fit statistic: chi\n", 54 | " Using Response (RMF) File ginga_lac.rsp for Source 1\n", 55 | "\n", 56 | "Spectral Data File: losum.pha Spectrum 2\n", 57 | "Net count rate (cts/s) for Spectrum:2 1.401e+02 +/- 3.549e-01\n", 58 | " Assigned to Data Group 2 and Plot Group 2\n", 59 | " Noticed Channels: 1-48\n", 60 | " Telescope: GINGA Instrument: LAC Channel Type: PHA\n", 61 | " Exposure Time: 1 sec\n", 62 | " Using fit statistic: chi\n", 63 | " Using Response (RMF) File ginga_lac.rsp for Source 1\n", 64 | "\n", 65 | "Response successfully loaded.\n", 66 | "Response successfully loaded.\n" 67 | ] 68 | } 69 | ], 70 | "source": [ 71 | "%cd data\n", 72 | "AllData(\"1:1 hisum.pha 2:2 losum.pha\")\n", 73 | "s1 = AllData(1)\n", 74 | "s2 = AllData(2)\n", 75 | "s1.response = \"ginga_lac.rsp\"\n", 76 | "s2.response = \"ginga_lac.rsp\"" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "Set up the model for the source. Here we will take the simple case of an absorbed power-law and set the model normalization to zero for the background spectrum. " 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 3, 89 | "metadata": { 90 | "scrolled": true 91 | }, 92 | "outputs": [ 93 | { 94 | "name": "stdout", 95 | "output_type": "stream", 96 | "text": [ 97 | "\n", 98 | "========================================================================\n", 99 | "Model phabs<1>*powerlaw<2> Source No.: 1 Active/On\n", 100 | "Model Model Component Parameter Unit Value\n", 101 | " par comp\n", 102 | " Data group: 1\n", 103 | " 1 1 phabs nH 10^22 1.00000 +/- 0.0 \n", 104 | " 2 2 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 105 | " 3 2 powerlaw norm 1.00000 +/- 0.0 \n", 106 | " Data group: 2\n", 107 | " 4 1 phabs nH 10^22 1.00000 = p1\n", 108 | " 5 2 powerlaw PhoIndex 1.00000 = p2\n", 109 | " 6 2 powerlaw norm 1.00000 = p3\n", 110 | "________________________________________________________________________\n", 111 | "\n", 112 | "\n", 113 | "Fit statistic : Chi-Squared 2.214313e+07 using 48 bins.\n", 114 | " Chi-Squared 3.817637e+08 using 48 bins.\n", 115 | "Total fit statistic 4.039068e+08 with 93 d.o.f.\n", 116 | "\n", 117 | "Test statistic : Chi-Squared 4.039068e+08 using 96 bins.\n", 118 | " Null hypothesis probability of 0.000000e+00 with 93 degrees of freedom\n", 119 | " Current data and model not fit yet.\n", 120 | "\n", 121 | "Fit statistic : Chi-Squared 2.214313e+07 using 48 bins.\n", 122 | " Chi-Squared 177171.1 using 48 bins.\n", 123 | "Total fit statistic 2.232030e+07 with 93 d.o.f.\n", 124 | "\n", 125 | "Test statistic : Chi-Squared 2.232030e+07 using 96 bins.\n", 126 | " Null hypothesis probability of 0.000000e+00 with 93 degrees of freedom\n", 127 | " Current data and model not fit yet.\n" 128 | ] 129 | } 130 | ], 131 | "source": [ 132 | "Model(\"phabs * pow\")\n", 133 | "m1 = AllModels(1)\n", 134 | "m2 = AllModels(2)\n", 135 | "m2(3).values = \"0.0,-1.0\"" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "Now we need to set up the background model for both datasets with the appropriate response matrices. " 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 4, 148 | "metadata": {}, 149 | "outputs": [ 150 | { 151 | "name": "stdout", 152 | "output_type": "stream", 153 | "text": [ 154 | "Response successfully loaded.\n", 155 | "\n", 156 | "Fit statistic : Chi-Squared 2.214313e+07 using 48 bins.\n", 157 | " Chi-Squared 177171.1 using 48 bins.\n", 158 | "Total fit statistic 2.232030e+07 with 93 d.o.f.\n", 159 | "\n", 160 | "Test statistic : Chi-Squared 2.232030e+07 using 96 bins.\n", 161 | " Null hypothesis probability of 0.000000e+00 with 93 degrees of freedom\n", 162 | " Current data and model not fit yet.\n", 163 | "Response successfully loaded.\n", 164 | "\n", 165 | "Fit statistic : Chi-Squared 2.214313e+07 using 48 bins.\n", 166 | " Chi-Squared 177171.1 using 48 bins.\n", 167 | "Total fit statistic 2.232030e+07 with 93 d.o.f.\n", 168 | "\n", 169 | "Test statistic : Chi-Squared 2.232030e+07 using 96 bins.\n", 170 | " Null hypothesis probability of 0.000000e+00 with 93 degrees of freedom\n", 171 | " Current data and model not fit yet.\n" 172 | ] 173 | } 174 | ], 175 | "source": [ 176 | "s1.multiresponse[1] = \"ginga_lac.rsp\"\n", 177 | "s2.multiresponse[1] = \"ginga_lac.rsp\"" 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "This tells XSPEC that both these datasets have a second model which must be multiplied by the appropriate response matrix for its contribution to the source region and for its contribution to the background region. This is likely to be the case for a standard imaging data where the response will only depend on the extraction region. Note that for a coded-aperture mask the situation may be more complicated with a different response for the source and the background even if they are extracted from the same region of the detector. We now define the background model to be used. In this case take the simple example of a single power-law " 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 5, 190 | "metadata": {}, 191 | "outputs": [ 192 | { 193 | "name": "stdout", 194 | "output_type": "stream", 195 | "text": [ 196 | "\n", 197 | "========================================================================\n", 198 | "Model myback:powerlaw<1> Source No.: 2 Active/On\n", 199 | "Model Model Component Parameter Unit Value\n", 200 | " par comp\n", 201 | " Data group: 1\n", 202 | " 1 1 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 203 | " 2 1 powerlaw norm 1.00000 +/- 0.0 \n", 204 | " Data group: 2\n", 205 | " 3 1 powerlaw PhoIndex 1.00000 = myback:p1\n", 206 | " 4 1 powerlaw norm 1.00000 = myback:p2\n", 207 | "________________________________________________________________________\n", 208 | "\n", 209 | "\n", 210 | "Fit statistic : Chi-Squared 9.779387e+07 using 48 bins.\n", 211 | " Chi-Squared 4.523427e+08 using 48 bins.\n", 212 | "Total fit statistic 5.501366e+08 with 91 d.o.f.\n", 213 | "\n", 214 | "Test statistic : Chi-Squared 5.501366e+08 using 96 bins.\n", 215 | " Null hypothesis probability of 0.000000e+00 with 91 degrees of freedom\n", 216 | " Current data and model not fit yet.\n" 217 | ] 218 | } 219 | ], 220 | "source": [ 221 | "m1_2 = Model(\"pow\",\"myback\",2)" 222 | ] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "metadata": {}, 227 | "source": [ 228 | "We have now set up XSPEC so that the source data is compared to a source model multiplied by the source response plus a background model multiplied by the background response and the background data is compared to the background model multiplied by the background response. The background models fitted to the source and background data are constrained to be the same. " 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": 6, 234 | "metadata": {}, 235 | "outputs": [ 236 | { 237 | "name": "stdout", 238 | "output_type": "stream", 239 | "text": [ 240 | "\n", 241 | "Parameters defined:\n", 242 | "========================================================================\n", 243 | "Model phabs<1>*powerlaw<2> Source No.: 1 Active/On\n", 244 | "Model Model Component Parameter Unit Value\n", 245 | " par comp\n", 246 | " Data group: 1\n", 247 | " 1 1 phabs nH 10^22 1.00000 +/- 0.0 \n", 248 | " 2 2 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 249 | " 3 2 powerlaw norm 1.00000 +/- 0.0 \n", 250 | " Data group: 2\n", 251 | " 4 1 phabs nH 10^22 1.00000 = p1\n", 252 | " 5 2 powerlaw PhoIndex 1.00000 = p2\n", 253 | " 6 2 powerlaw norm 0.0 frozen\n", 254 | "________________________________________________________________________\n", 255 | "\n", 256 | "========================================================================\n", 257 | "Model myback:powerlaw<1> Source No.: 2 Active/On\n", 258 | "Model Model Component Parameter Unit Value\n", 259 | " par comp\n", 260 | " Data group: 1\n", 261 | " 1 1 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 262 | " 2 1 powerlaw norm 1.00000 +/- 0.0 \n", 263 | " Data group: 2\n", 264 | " 3 1 powerlaw PhoIndex 1.00000 = myback:p1\n", 265 | " 4 1 powerlaw norm 1.00000 = myback:p2\n", 266 | "________________________________________________________________________\n", 267 | "\n" 268 | ] 269 | } 270 | ], 271 | "source": [ 272 | "AllModels.show()" 273 | ] 274 | }, 275 | { 276 | "cell_type": "code", 277 | "execution_count": null, 278 | "metadata": {}, 279 | "outputs": [], 280 | "source": [] 281 | } 282 | ], 283 | "metadata": { 284 | "kernelspec": { 285 | "display_name": "Python 3 (ipykernel)", 286 | "language": "python", 287 | "name": "python3" 288 | }, 289 | "language_info": { 290 | "codemirror_mode": { 291 | "name": "ipython", 292 | "version": 3 293 | }, 294 | "file_extension": ".py", 295 | "mimetype": "text/x-python", 296 | "name": "python", 297 | "nbconvert_exporter": "python", 298 | "pygments_lexer": "ipython3", 299 | "version": "3.12.6" 300 | } 301 | }, 302 | "nbformat": 4, 303 | "nbformat_minor": 4 304 | } 305 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/README-checkpoint.md: -------------------------------------------------------------------------------- 1 | # PyXspec-Jupyter-notebooks 2 | A collection of Jupyter notebooks illustrating PyXspec analysis 3 | 4 | The PyXspecWalkthroughN notebooks are for the examples in the Walks through XSPEC section of the manual. Those whose names include Matplotlib use matplotlib to do the plotting while the others use the native XSPEC plotting using the pgplot svg driver. 5 | 6 | A brief summary for each N in PyXspecWalkthroughN is: 7 | 8 | 1 - Fitting Models to Data: An Old Example from EXOSAT 9 | 10 | 2 - Simultaneous Fitting 11 | 12 | 3 - Multiple Models: a Background Modeling Example 13 | 14 | 4 - Using XSPEC to Simulate Data: an Example for Chandra 15 | 16 | 5 - Producing Plots: Modifying the Defaults 17 | 18 | These notebooks assume XSPEC v12.12 or later. 19 | -------------------------------------------------------------------------------- /PyXspecWalkthrough2Matplotlib.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# uncomment the line below to make matplotlib plots dynamic\n", 10 | "#%matplotlib notebook\n", 11 | "import matplotlib\n", 12 | "import numpy as np\n", 13 | "import matplotlib.pyplot as plt\n", 14 | "\n", 15 | "# older versions of Jupyter may need wurlitzer in order to redirect the C output to the notebook\n", 16 | "# %load_ext wurlitzer\n", 17 | "\n", 18 | "from xspec import *" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "##Simultaneous Fitting\n", 26 | "\n", 27 | "XSPEC has the very useful facility of allowing models to be fitted simultaneously to more than one data file. It is even possible to group files together and to fit different models simultaneously. Reasons for fitting in this manner include:\n", 28 | "\n", 29 | " The same target is observed at several epochs but, although the source stays constant, the response matrix has changed. When this happens, the data files cannot be added together; they have to be fitted separately. Fitting the data files simultaneously yields tighter constraints.\n", 30 | " The same target is observed with different instruments. All the instruments on Suzaku, for example, observe in the same direction simultaneously. As far as XSPEC is concerned, this is just like the previous case: two data files with two responses fitted simultaneously with the same model.\n", 31 | " Different targets are observed, but the user wants to fit the same model to each data file with some parameters shared and some allowed to vary separately. For example, if we have a series of spectra from a variable AGN, we might want to fit them simultaneously with a model that has the same, common photon index but separately vary the normalization and absorption.\n", 32 | "\n", 33 | "Other scenarios are possible--the important thing is to recognize the flexibility of XSPEC in this regard.\n", 34 | "\n", 35 | "As an example we will look at a case of fitting the same model to two different data files but where not all the parameters are identical. Again, this is an older dataset that provides a simpler illustration than more modern data. The massive X-ray binary Centaurus X-3 was observed with the LAC on Ginga in 1989. Its flux level before eclipse was much lower than the level after eclipse. Here, we'll use XSPEC to see whether spectra from these two phases can be fitted with the same model, which differs only in the amount of absorption. The spectra and corresponding response matrices were obtained from the HEASARC and are available from https://heasarc.gsfc.nasa.gov/docs/xanadu/xspec/walkthrough.tar.gz\n", 36 | "\n", 37 | "This kind of fitting relies on introducing an extra dimension, the group, to the indexing of the data files. The files in each group share the same model but not necessarily the same parameter values, which may be shared as common to all the groups or varied separately from group to group. Although each group may contain more than one file, there is only one file in each of the two groups in this example. Groups are specified with the data command, with the group number preceding the file number, like this: " 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 2, 43 | "metadata": {}, 44 | "outputs": [ 45 | { 46 | "name": "stdout", 47 | "output_type": "stream", 48 | "text": [ 49 | "/Users/karnaud/Jupyter-notebooks/data\n", 50 | "\n", 51 | "2 spectra in use\n", 52 | " \n", 53 | "Spectral Data File: losum.pha Spectrum 1\n", 54 | "Net count rate (cts/s) for Spectrum:1 1.401e+02 +/- 3.549e-01\n", 55 | " Assigned to Data Group 1 and Plot Group 1\n", 56 | " Noticed Channels: 1-48\n", 57 | " Telescope: GINGA Instrument: LAC Channel Type: PHA\n", 58 | " Exposure Time: 1 sec\n", 59 | " Using fit statistic: chi\n", 60 | " Using Response (RMF) File ginga_lac.rsp for Source 1\n", 61 | "\n", 62 | "Spectral Data File: hisum.pha Spectrum 2\n", 63 | "Net count rate (cts/s) for Spectrum:2 1.371e+03 +/- 3.123e+00\n", 64 | " Assigned to Data Group 2 and Plot Group 2\n", 65 | " Noticed Channels: 1-48\n", 66 | " Telescope: GINGA Instrument: LAC Channel Type: PHA\n", 67 | " Exposure Time: 1 sec\n", 68 | " Using fit statistic: chi\n", 69 | " Using Response (RMF) File ginga_lac.rsp for Source 1\n", 70 | "\n" 71 | ] 72 | } 73 | ], 74 | "source": [ 75 | "%cd data\n", 76 | "AllData(\"1:1 losum 2:2 hisum\")" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "Here, the first group makes up the file losum.pha, which contains the spectrum of all the low, pre-eclipse emission. The second group makes up the second file, hisum.pha, which contains all the high, post-eclipse emission. Note that file number is \"absolute\" in the sense that it is independent of group number. Thus, if there were three files in each of the two groups (lo1.pha, lo2.pha, lo3.pha, hi1.pha, hi2.pha, and hi3.pha, say), rather than one, the six files would be specified as \"1:1 lo1 1:2 lo2 1:3 lo3 2:4 hi1 2:5 hi2 2:6 hi3\". The ignore method works on file number, and does not take group number into account. So, to ignore channels 1-3 and 37-48 of both files: " 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 3, 89 | "metadata": { 90 | "scrolled": true 91 | }, 92 | "outputs": [ 93 | { 94 | "name": "stdout", 95 | "output_type": "stream", 96 | "text": [ 97 | " 3 channels (1,3) ignored in spectrum # 1\n", 98 | " 3 channels (1,3) ignored in spectrum # 2\n", 99 | " 12 channels (37,48) ignored in spectrum # 1\n", 100 | " 12 channels (37,48) ignored in spectrum # 2\n", 101 | "\n" 102 | ] 103 | } 104 | ], 105 | "source": [ 106 | "AllData.ignore(\"1-3 37-48\")" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "The model we'll use at first to fit the two files is an absorbed power law with a high-energy cut-off: " 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 4, 119 | "metadata": {}, 120 | "outputs": [ 121 | { 122 | "data": { 123 | "text/plain": [ 124 | "" 125 | ] 126 | }, 127 | "execution_count": 4, 128 | "metadata": {}, 129 | "output_type": "execute_result" 130 | }, 131 | { 132 | "name": "stdout", 133 | "output_type": "stream", 134 | "text": [ 135 | "\n", 136 | "========================================================================\n", 137 | "Model phabs<1>*highecut<2>*powerlaw<3> Source No.: 1 Active/On\n", 138 | "Model Model Component Parameter Unit Value\n", 139 | " par comp\n", 140 | " Data group: 1\n", 141 | " 1 1 phabs nH 10^22 1.00000 +/- 0.0 \n", 142 | " 2 2 highecut cutoffE keV 10.0000 +/- 0.0 \n", 143 | " 3 2 highecut foldE keV 15.0000 +/- 0.0 \n", 144 | " 4 3 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 145 | " 5 3 powerlaw norm 1.00000 +/- 0.0 \n", 146 | " Data group: 2\n", 147 | " 6 1 phabs nH 10^22 1.00000 = p1\n", 148 | " 7 2 highecut cutoffE keV 10.0000 = p2\n", 149 | " 8 2 highecut foldE keV 15.0000 = p3\n", 150 | " 9 3 powerlaw PhoIndex 1.00000 = p4\n", 151 | " 10 3 powerlaw norm 1.00000 = p5\n", 152 | "________________________________________________________________________\n", 153 | "\n", 154 | "\n", 155 | "Fit statistic : Chi-Squared 3.256708e+08 using 33 bins.\n", 156 | " Chi-Squared 4.084839e+06 using 33 bins.\n", 157 | "Total fit statistic 3.297556e+08 with 61 d.o.f.\n", 158 | "\n", 159 | "Test statistic : Chi-Squared 3.297556e+08 using 66 bins.\n", 160 | " Null hypothesis probability of 0.000000e+00 with 61 degrees of freedom\n", 161 | " Current data and model not fit yet.\n" 162 | ] 163 | } 164 | ], 165 | "source": [ 166 | "Model(\"phabs * highecut(pow)\")" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "Notice how the summary of the model, displayed immediately above, is different now that we have two groups, as opposed to one. We can see that of the 10 model parameters, 5 for each data group and, by default, the parameters for the second data group are linked to those for the first. Let us suppose that we have a theory that the difference between the two spectra is a change in the absorption. We want to remove the link between parameters 1 and 6 and the fit. When there are two datagroups there are two separate model objects created so to change the sixth parameter, which is the first parameter of the model for the second datagroup we do:" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 5, 179 | "metadata": {}, 180 | "outputs": [ 181 | { 182 | "name": "stdout", 183 | "output_type": "stream", 184 | "text": [ 185 | "\n", 186 | "Fit statistic : Chi-Squared 3.256708e+08 using 33 bins.\n", 187 | " Chi-Squared 4.084839e+06 using 33 bins.\n", 188 | "Total fit statistic 3.297556e+08 with 60 d.o.f.\n", 189 | "\n", 190 | "Test statistic : Chi-Squared 3.297556e+08 using 66 bins.\n", 191 | " Null hypothesis probability of 0.000000e+00 with 60 degrees of freedom\n", 192 | " Current data and model not fit yet.\n", 193 | " Parameters\n", 194 | "Chi-Squared |beta|/N Lvl 1:nH 2:cutoffE 3:foldE 4:PhoIndex 5:norm 6:nH\n", 195 | "220543 9867.56 -3 0.333148 14.2798 36.6028 0.147414 0.00411629 0.283885\n", 196 | "215947 201943 -4 0.128858 13.1325 14.8783 0.00259899 0.00341326 0.0366783\n", 197 | "215135 171911 -5 0.368941 14.8072 7.49843 0.0640761 0.00381547 0.00600141\n", 198 | "214490 644803 -6 0.441643 14.5379 8.82389 0.0643614 0.00386068 0.00252599\n", 199 | "214432 468127 -7 0.485919 14.5043 9.02904 0.0669875 0.00388596 0.000811596\n", 200 | "214429 456922 -2 0.510309 14.4829 8.96366 0.0679087 0.00389913 0.000388265\n", 201 | "214404 463354 -3 0.514668 14.4459 9.13292 0.0667926 0.00389109 0.000175845\n", 202 | "214320 451243 -4 0.571311 14.4601 9.11420 0.0706216 0.00393704 7.03735e-05\n", 203 | "214298 428465 -1 0.586668 14.5286 9.08019 0.0723297 0.00394936 2.16957e-05\n", 204 | "214193 421731 -2 0.716931 14.8688 8.09433 0.0833144 0.00407428 9.80346e-06\n", 205 | "Number of trials exceeded: continue fitting? 214052 394059 0 0.757403 14.7708 8.38901 0.0825967 0.00409316 2.40852e-06\n", 206 | "213638 335202 -1 1.11498 14.5947 8.85045 0.0853738 0.00425318 2.99592e-07\n", 207 | "212904 85197.4 -2 2.09752 14.7079 9.38267 0.172575 0.00517626 1.05067e-07\n", 208 | "212806 219741 -3 4.10472 15.4754 9.83384 0.350441 0.00749112 1.94492e-08\n", 209 | "***Warning: Zero alpha-matrix diagonal element for parameter 6\n", 210 | " Parameter 6 is pegged at 1.94492e-08 due to zero or negative pivot element, likely\n", 211 | " caused by the fit being insensitive to the parameter.\n", 212 | "209758 552859 -2 6.51448 15.6778 10.0425 0.451960 0.0102006 1.94492e-08\n", 213 | "207240 269853 -2 10.3620 15.9862 10.4370 0.603439 0.0148987 1.94492e-08\n", 214 | "205214 291214 -2 17.5494 16.3449 11.1012 0.835406 0.0257588 1.94492e-08\n", 215 | "191984 324874 -1 23.3363 15.5371 11.0329 0.833163 0.0328918 1.94492e-08\n", 216 | "185862 71246 -1 30.2632 14.5910 11.2310 0.868496 0.0397037 1.94492e-08\n", 217 | "Number of trials exceeded: continue fitting? 177767 65291.1 -1 39.4296 13.3246 11.7797 0.908941 0.0494062 1.94492e-08\n", 218 | "164920 69446.3 -1 52.8504 11.2860 12.3169 0.943052 0.0642380 1.94492e-08\n", 219 | "138495 80667.9 -1 76.6503 7.08944 11.8128 0.928434 0.0906922 1.94492e-08\n", 220 | "125659 124599 0 80.1719 7.05271 11.2810 0.902787 0.100909 1.94492e-08\n", 221 | "120907 60996 -1 103.087 4.80632 6.79762 0.832274 0.141486 1.94492e-08\n", 222 | "90955.2 113861 -2 128.202 8.41987 5.95082 0.817197 0.160683 1.94492e-08\n", 223 | "85546.6 35356.6 -3 135.188 5.45293 6.06266 0.573823 0.122943 1.94492e-08\n", 224 | "84749.1 35401.1 -3 140.836 7.61059 5.85790 0.738242 0.145785 1.94492e-08\n", 225 | "84709.3 12048.3 -3 140.767 5.59164 5.65659 0.511520 0.114741 1.94492e-08\n", 226 | "84255.5 35235.5 -3 142.272 7.29392 5.75903 0.696373 0.138805 1.94492e-08\n", 227 | "Number of trials exceeded: continue fitting? 83193.5 19638.5 -2 140.908 6.11129 5.80183 0.603226 0.134340 1.94492e-08\n", 228 | "83069.3 3239.41 -3 141.654 6.84792 5.58914 0.627374 0.133392 1.94492e-08\n", 229 | "82939.2 437.368 -2 140.578 6.24236 5.61527 0.579925 0.129147 1.94492e-08\n", 230 | "82909.3 1141.99 -3 140.975 6.63680 5.52915 0.597574 0.129213 1.94492e-08\n", 231 | "82870.3 80.4941 -2 140.432 6.34338 5.53871 0.573720 0.127180 1.94492e-08\n", 232 | "82860.4 260.727 -3 140.616 6.49770 5.49369 0.577277 0.126430 1.94492e-08\n", 233 | "82855.3 31.242 -2 140.408 6.38373 5.49676 0.567694 0.125609 1.94492e-08\n", 234 | "82854.1 54.0641 -3 140.480 6.43266 5.47749 0.567343 0.125052 1.94492e-08\n", 235 | "82853.6 5.55634 -4 140.452 6.38186 5.46413 0.558930 0.123855 1.94492e-08\n", 236 | "82852.7 47.8308 -2 140.486 6.40922 5.46291 0.561266 0.124062 1.94492e-08\n", 237 | "Number of trials exceeded: continue fitting? 82852.4 14.8929 -3 140.471 6.40583 5.46869 0.562579 0.124368 1.94492e-08\n", 238 | "82852.4 2.82098 1 140.471 6.40583 5.46869 0.562579 0.124368 1.94492e-08\n", 239 | "***Warning: Zero alpha-matrix diagonal element for parameter 6\n", 240 | " Parameter 6 is pegged at 1.94492e-08 due to zero or negative pivot element, likely\n", 241 | " caused by the fit being insensitive to the parameter.\n", 242 | "82852.4 2.37912 0 140.470 6.40584 5.46869 0.562579 0.124368 1.94492e-08\n", 243 | "============================================================\n", 244 | " Variances and Principal Axes\n", 245 | " 1 2 3 4 5 \n", 246 | " 3.5982E-08| -0.0004 0.0169 0.0181 -0.2652 0.9639 \n", 247 | " 8.1972E-06| -0.0017 0.1112 0.2060 -0.9359 -0.2633 \n", 248 | " 5.8370E-04| -0.0238 0.3414 -0.9263 -0.1545 -0.0311 \n", 249 | " 2.5722E-03| 0.0224 -0.9327 -0.3146 -0.1730 -0.0253 \n", 250 | " 1.2403E-01| 0.9995 0.0293 -0.0147 -0.0015 -0.0002 \n", 251 | "------------------------------------------------------------\n", 252 | "\n", 253 | "============================================================\n", 254 | " Covariance Matrix\n", 255 | " 1 2 3 4 5 \n", 256 | " 1.239e-01 3.571e-03 -1.824e-03 -1.959e-04 -2.837e-05\n", 257 | " 3.571e-03 2.412e-03 5.172e-04 3.779e-04 5.358e-05\n", 258 | " -1.824e-03 5.172e-04 7.825e-04 2.247e-04 3.727e-05\n", 259 | " -1.959e-04 3.779e-04 2.247e-04 9.840e-05 1.613e-05\n", 260 | " -2.837e-05 5.358e-05 3.727e-05 1.613e-05 2.824e-06\n", 261 | "------------------------------------------------------------\n", 262 | "\n", 263 | "========================================================================\n", 264 | "Model phabs<1>*highecut<2>*powerlaw<3> Source No.: 1 Active/On\n", 265 | "Model Model Component Parameter Unit Value\n", 266 | " par comp\n", 267 | " Data group: 1\n", 268 | " 1 1 phabs nH 10^22 140.470 +/- 0.351989 \n", 269 | " 2 2 highecut cutoffE keV 6.40584 +/- 4.91132E-02 \n", 270 | " 3 2 highecut foldE keV 5.46869 +/- 2.79734E-02 \n", 271 | " 4 3 powerlaw PhoIndex 0.562579 +/- 9.91965E-03 \n", 272 | " 5 3 powerlaw norm 0.124368 +/- 1.68042E-03 \n", 273 | " Data group: 2\n", 274 | " 6 1 phabs nH 10^22 1.94492E-08 +/- -1.00000 \n", 275 | " 7 2 highecut cutoffE keV 6.40584 = p2\n", 276 | " 8 2 highecut foldE keV 5.46869 = p3\n", 277 | " 9 3 powerlaw PhoIndex 0.562579 = p4\n", 278 | " 10 3 powerlaw norm 0.124368 = p5\n", 279 | "________________________________________________________________________\n", 280 | "\n", 281 | "\n", 282 | "Fit statistic : Chi-Squared 51448.96 using 33 bins.\n", 283 | " Chi-Squared 31403.45 using 33 bins.\n", 284 | "Total fit statistic 82852.41 with 60 d.o.f.\n", 285 | "\n", 286 | "Test statistic : Chi-Squared 82852.41 using 66 bins.\n", 287 | " Null hypothesis probability of 0.00e+00 with 60 degrees of freedom\n" 288 | ] 289 | } 290 | ], 291 | "source": [ 292 | "m1 = AllModels(1)\n", 293 | "m2 = AllModels(2)\n", 294 | "m2(1).untie()\n", 295 | "Fit.perform()" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": 6, 301 | "metadata": {}, 302 | "outputs": [], 303 | "source": [ 304 | "Plot.device=\"/null\"\n", 305 | "Plot.xAxis=\"keV\"\n", 306 | "Plot(\"data resid\")\n", 307 | "energies = Plot.x()\n", 308 | "edeltas = Plot.xErr()\n", 309 | "rates = Plot.y(1,1)\n", 310 | "errors = Plot.yErr(1,1)\n", 311 | "rates2 = Plot.y(2,1)\n", 312 | "errors2 = Plot.yErr(2,1)\n", 313 | "foldedmodel = Plot.model()\n", 314 | "foldedmodel2 = Plot.model(2)\n", 315 | "dataLabels = Plot.labels(1)\n", 316 | "residLabels = Plot.labels(2)\n", 317 | "# note that for matplotlib step plots we need an x-axis array which includes the start and end value for each\n", 318 | "# bin and the y-axis has to be the same size with an extra value added equal to the value of the last bin\n", 319 | "nE = len(energies)\n", 320 | "stepenergies = list()\n", 321 | "for i in range(nE):\n", 322 | " stepenergies.append(energies[i] - edeltas[i])\n", 323 | "stepenergies.append(energies[-1]+edeltas[-1])\n", 324 | "foldedmodel.append(foldedmodel[-1])\n", 325 | "foldedmodel2.append(foldedmodel2[-1])\n", 326 | "resid = Plot.y(1,2)\n", 327 | "resid.append(resid[-1])\n", 328 | "resid2 = Plot.y(2,2)\n", 329 | "resid2.append(resid2[-1])" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": 7, 335 | "metadata": {}, 336 | "outputs": [ 337 | { 338 | "data": { 339 | "text/plain": [ 340 | "" 341 | ] 342 | }, 343 | "execution_count": 7, 344 | "metadata": {}, 345 | "output_type": "execute_result" 346 | }, 347 | { 348 | "data": { 349 | "image/png": "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\n", 350 | "text/plain": [ 351 | "
" 352 | ] 353 | }, 354 | "metadata": { 355 | "needs_background": "light" 356 | }, 357 | "output_type": "display_data" 358 | } 359 | ], 360 | "source": [ 361 | "plt.subplot(211)\n", 362 | "plt.ylabel(dataLabels[1])\n", 363 | "plt.title(dataLabels[2])\n", 364 | "plt.errorbar(energies,rates,xerr=edeltas,yerr=errors,fmt='.',color='b')\n", 365 | "plt.errorbar(energies,rates2,xerr=edeltas,yerr=errors2,fmt='.',color='r')\n", 366 | "plt.step(stepenergies,foldedmodel,where='post',color='b')\n", 367 | "plt.step(stepenergies,foldedmodel2,where='post',color='r')\n", 368 | "plt.subplot(212)\n", 369 | "plt.xlabel(residLabels[0])\n", 370 | "plt.ylabel(residLabels[1])\n", 371 | "plt.step(stepenergies,resid,where='post',color='b')\n", 372 | "plt.step(stepenergies,resid2,where='post',color='r')\n", 373 | "plt.hlines(0.0,stepenergies[0],stepenergies[-1],linestyles='dashed')" 374 | ] 375 | }, 376 | { 377 | "cell_type": "markdown", 378 | "metadata": {}, 379 | "source": [ 380 | "Clearly our assumption that only a change in absorption can account for the spectral variation before and after eclipse is clearly wrong. Perhaps scattering also plays a role in reducing the flux before eclipse. This could be modeled (simply at first) by allowing the normalization of the power law to be smaller before eclipse than after eclipse. To decouple tied parameters, we can change the parameter value in the second group to a value - any value - different from that in the first group (changing the value in the first group has the effect of changing both without decoupling)." 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": 8, 386 | "metadata": {}, 387 | "outputs": [ 388 | { 389 | "name": "stdout", 390 | "output_type": "stream", 391 | "text": [ 392 | "\n", 393 | "Fit statistic : Chi-Squared 51448.96 using 33 bins.\n", 394 | " Chi-Squared 9.949616e+06 using 33 bins.\n", 395 | "Total fit statistic 1.000107e+07 with 59 d.o.f.\n", 396 | "\n", 397 | "Test statistic : Chi-Squared 1.000107e+07 using 66 bins.\n", 398 | " Null hypothesis probability of 0.000000e+00 with 59 degrees of freedom\n", 399 | " Current data and model not fit yet.\n", 400 | " Parameters\n", 401 | "Chi-Squared |beta|/N Lvl 1:nH 2:cutoffE 3:foldE 4:PhoIndex 5:norm 6:nH 10:norm\n", 402 | "***Warning: Zero alpha-matrix diagonal element for parameter 6\n", 403 | " Parameter 6 is pegged at 1.94492e-08 due to zero or negative pivot element, likely\n", 404 | " caused by the fit being insensitive to the parameter.\n", 405 | "28403.7 173861 -3 37.3744 5.67197 8.29470 0.567248 0.0366093 1.94492e-08 0.120893\n", 406 | "21282.9 140465 -4 30.9428 5.14085 9.36123 0.510361 0.0227609 1.94492e-08 0.111853\n", 407 | "20084.6 93537.7 -3 29.4438 3.69099 8.19123 0.345370 0.0208368 1.94492e-08 0.0937947\n", 408 | "18713.6 53644.7 -2 26.7473 2.98087 8.12373 0.292166 0.0202251 1.94492e-08 0.0956424\n", 409 | "18589.2 2023.14 -2 25.4560 2.85357 7.94011 0.264508 0.0192985 1.94492e-08 0.0934280\n", 410 | "18522.7 1759.82 -2 24.6101 2.72212 7.82086 0.240585 0.0186062 1.94492e-08 0.0914817\n", 411 | "18505.2 1160.36 -3 23.6803 2.18058 7.31869 0.150112 0.0169913 1.94492e-08 0.0853591\n", 412 | "18421.9 20159.6 -4 23.2816 2.28459 7.29900 0.141862 0.0165769 1.94492e-08 0.0839997\n", 413 | "18419.5 498.919 -5 23.0436 2.18316 7.27728 0.136536 0.0165993 1.94492e-08 0.0844377\n", 414 | "Number of trials exceeded: continue fitting? 18418.8 113.228 -6 22.9231 2.23879 7.29215 0.139137 0.0164971 1.94492e-08 0.0840927\n", 415 | "18418.4 102.782 -7 22.8251 2.17674 7.28009 0.136214 0.0165320 1.94492e-08 0.0844125\n", 416 | "18418.4 47.6225 -8 22.7868 2.23695 7.29323 0.138827 0.0164480 1.94492e-08 0.0840383\n", 417 | "18418.2 75.1688 -9 22.7378 2.16879 7.27940 0.135716 0.0165080 1.94492e-08 0.0844170\n", 418 | "18418.2 57.0657 -3 22.7264 2.21083 7.28770 0.137469 0.0164536 1.94492e-08 0.0841571\n", 419 | "18418.1 24.5332 -3 22.7079 2.18439 7.28445 0.136629 0.0164854 1.94492e-08 0.0843439\n", 420 | "18418.1 16.3983 -3 22.7047 2.20490 7.28788 0.137394 0.0164577 1.94492e-08 0.0842082\n", 421 | "18418.1 3.17486 -2 22.6987 2.19951 7.28763 0.137275 0.0164644 1.94492e-08 0.0842500\n", 422 | "18418.1 10.0775 2 22.6987 2.19951 7.28763 0.137275 0.0164644 1.94492e-08 0.0842500\n", 423 | "***Warning: Zero alpha-matrix diagonal element for parameter 6\n", 424 | " Parameter 6 is pegged at 1.94492e-08 due to zero or negative pivot element, likely\n", 425 | " caused by the fit being insensitive to the parameter.\n", 426 | "18418.1 10.0125 3 22.6987 2.19951 7.28763 0.137275 0.0164644 1.94492e-08 0.0842500\n", 427 | "======================================================================\n", 428 | " Variances and Principal Axes\n", 429 | " 1 2 3 4 5 10 \n", 430 | " 1.6950E-09| 0.0003 -0.0023 -0.0023 0.0359 -0.9994 -0.0005 \n", 431 | " 2.2525E-08| 0.0000 0.0111 0.0139 -0.1852 -0.0072 0.9825 \n", 432 | " 6.9749E-06| -0.0056 -0.0077 -0.1624 0.9685 0.0351 0.1852 \n", 433 | " 2.7695E-03| -0.0005 -0.2333 0.9597 0.1554 0.0039 0.0183 \n", 434 | " 2.2852E-02| 0.4732 -0.8566 -0.2018 -0.0389 0.0011 0.0052 \n", 435 | " 4.1543E-02| 0.8809 0.4600 0.1079 0.0272 -0.0001 -0.0016 \n", 436 | "----------------------------------------------------------------------\n", 437 | "\n", 438 | "========================================================================\n", 439 | " Covariance Matrix\n", 440 | " 1 2 3 4 5 6 \n", 441 | " 3.736e-02 7.570e-03 1.766e-03 5.729e-04 1.046e-05 -2.535e-06\n", 442 | " 7.570e-03 2.571e-02 5.392e-03 1.181e-03 -2.587e-05 -1.439e-04\n", 443 | " 1.766e-03 5.392e-03 3.965e-03 7.133e-04 4.823e-06 1.748e-05\n", 444 | " 5.729e-04 1.181e-03 7.133e-04 1.388e-04 8.394e-07 2.723e-06\n", 445 | " 1.046e-05 -2.587e-05 4.823e-06 8.394e-07 8.228e-08 3.820e-07\n", 446 | " -2.535e-06 -1.439e-04 1.748e-05 2.723e-06 3.820e-07 1.914e-06\n", 447 | "------------------------------------------------------------------------\n", 448 | "\n", 449 | "========================================================================\n", 450 | "Model phabs<1>*highecut<2>*powerlaw<3> Source No.: 1 Active/On\n", 451 | "Model Model Component Parameter Unit Value\n", 452 | " par comp\n", 453 | " Data group: 1\n", 454 | " 1 1 phabs nH 10^22 22.6987 +/- 0.193277 \n", 455 | " 2 2 highecut cutoffE keV 2.19951 +/- 0.160342 \n", 456 | " 3 2 highecut foldE keV 7.28763 +/- 6.29704E-02 \n", 457 | " 4 3 powerlaw PhoIndex 0.137275 +/- 1.17796E-02 \n", 458 | " 5 3 powerlaw norm 1.64644E-02 +/- 2.86840E-04 \n", 459 | " Data group: 2\n", 460 | " 6 1 phabs nH 10^22 1.94492E-08 +/- -1.00000 \n", 461 | " 7 2 highecut cutoffE keV 2.19951 = p2\n", 462 | " 8 2 highecut foldE keV 7.28763 = p3\n", 463 | " 9 3 powerlaw PhoIndex 0.137275 = p4\n", 464 | " 10 3 powerlaw norm 8.42500E-02 +/- 1.38346E-03 \n", 465 | "________________________________________________________________________\n", 466 | "\n", 467 | "\n", 468 | "Fit statistic : Chi-Squared 16962.33 using 33 bins.\n", 469 | " Chi-Squared 1455.78 using 33 bins.\n", 470 | "Total fit statistic 18418.11 with 59 d.o.f.\n", 471 | "\n", 472 | "Test statistic : Chi-Squared 18418.11 using 66 bins.\n", 473 | " Null hypothesis probability of 0.00e+00 with 59 degrees of freedom\n" 474 | ] 475 | } 476 | ], 477 | "source": [ 478 | "m2.powerlaw.norm = 1.0\n", 479 | "Fit.perform()" 480 | ] 481 | }, 482 | { 483 | "cell_type": "code", 484 | "execution_count": 9, 485 | "metadata": {}, 486 | "outputs": [], 487 | "source": [ 488 | "Plot(\"data resid\")\n", 489 | "energies = Plot.x()\n", 490 | "edeltas = Plot.xErr()\n", 491 | "rates = Plot.y(1,1)\n", 492 | "errors = Plot.yErr(1,1)\n", 493 | "rates2 = Plot.y(2,1)\n", 494 | "errors2 = Plot.yErr(2,1)\n", 495 | "foldedmodel = Plot.model()\n", 496 | "foldedmodel2 = Plot.model(2)\n", 497 | "dataLabels = Plot.labels(1)\n", 498 | "residLabels = Plot.labels(2)\n", 499 | "# note that for matplotlib step plots we need an x-axis array which includes the start and end value for each\n", 500 | "# bin and the y-axis has to be the same size with an extra value added equal to the value of the last bin\n", 501 | "nE = len(energies)\n", 502 | "stepenergies = list()\n", 503 | "for i in range(nE):\n", 504 | " stepenergies.append(energies[i] - edeltas[i])\n", 505 | "stepenergies.append(energies[-1]+edeltas[-1])\n", 506 | "foldedmodel.append(foldedmodel[-1])\n", 507 | "foldedmodel2.append(foldedmodel2[-1])\n", 508 | "resid = Plot.y(1,2)\n", 509 | "resid.append(resid[-1])\n", 510 | "resid2 = Plot.y(2,2)\n", 511 | "resid2.append(resid2[-1])" 512 | ] 513 | }, 514 | { 515 | "cell_type": "code", 516 | "execution_count": 10, 517 | "metadata": {}, 518 | "outputs": [ 519 | { 520 | "data": { 521 | "text/plain": [ 522 | "" 523 | ] 524 | }, 525 | "execution_count": 10, 526 | "metadata": {}, 527 | "output_type": "execute_result" 528 | }, 529 | { 530 | "data": { 531 | "image/png": "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\n", 532 | "text/plain": [ 533 | "
" 534 | ] 535 | }, 536 | "metadata": { 537 | "needs_background": "light" 538 | }, 539 | "output_type": "display_data" 540 | } 541 | ], 542 | "source": [ 543 | "plt.subplot(211)\n", 544 | "plt.yscale('log')\n", 545 | "plt.ylabel(dataLabels[1])\n", 546 | "plt.title(dataLabels[2])\n", 547 | "plt.errorbar(energies,rates,xerr=edeltas,yerr=errors,fmt='.',color='b')\n", 548 | "plt.errorbar(energies,rates2,xerr=edeltas,yerr=errors2,fmt='.',color='r')\n", 549 | "plt.step(stepenergies,foldedmodel,where='post',color='b')\n", 550 | "plt.step(stepenergies,foldedmodel2,where='post',color='r')\n", 551 | "plt.subplot(212)\n", 552 | "plt.xlabel(residLabels[0])\n", 553 | "plt.ylabel(residLabels[1])\n", 554 | "plt.step(stepenergies,resid,where='post',color='b')\n", 555 | "plt.step(stepenergies,resid2,where='post',color='r')\n", 556 | "plt.hlines(0.0,stepenergies[0],stepenergies[-1],linestyles='dashed')" 557 | ] 558 | }, 559 | { 560 | "cell_type": "markdown", 561 | "metadata": {}, 562 | "source": [ 563 | "This decoupling improves the fit, but it still clearly not good. Indeed, this simple attempt to account for the spectral variability in terms of \"blanket\" cold absorption and scattering does not work. More sophisticated models, involving additional components and partial absorption, should be tried." 564 | ] 565 | } 566 | ], 567 | "metadata": { 568 | "kernelspec": { 569 | "display_name": "Python 3 (ipykernel)", 570 | "language": "python", 571 | "name": "python3" 572 | }, 573 | "language_info": { 574 | "codemirror_mode": { 575 | "name": "ipython", 576 | "version": 3 577 | }, 578 | "file_extension": ".py", 579 | "mimetype": "text/x-python", 580 | "name": "python", 581 | "nbconvert_exporter": "python", 582 | "pygments_lexer": "ipython3", 583 | "version": "3.12.6" 584 | } 585 | }, 586 | "nbformat": 4, 587 | "nbformat_minor": 4 588 | } 589 | -------------------------------------------------------------------------------- /PyXspecWalkthrough3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# older versions of Jupyter may need wurlitzer in order to redirect the C output to the notebook\n", 10 | "# %load_ext wurlitzer\n", 11 | "\n", 12 | "import IPython.display\n", 13 | "\n", 14 | "from xspec import *" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "##Multiple Models: a Background Modeling Example\n", 22 | "\n", 23 | "We now demonstrate how to fit multiple models, each with their own response, to the same dataset. There are several reasons why this may be useful, for instance:\n", 24 | "\n", 25 | " We are using data from a coded aperture mask. If there are multiple sources in the field they will all contribute to the spectrum from each detector. However, each source may have a different response due to its position.\n", 26 | " We are observing an extended source using a telescope whose PSF is large enough that the signal from different regions are mixed together. In this case we will want to analyze spectra from all regions of the source simultaneously with each spectrum having a contribution from the model in other regions.\n", 27 | " We wish to model the background spectrum that includes a particle component. The particle background will have a different response from the X-ray background because the particles come from all directions, not just down the telescope.\n", 28 | "\n", 29 | "We will demonstrate the third example here. Suppose we have a model for the background spectrum that requires a different response to that for the source spectrum. The spectra and corresponding response matrices were obtained from the HEASARC and are available from https://heasarc.gsfc.nasa.gov/docs/xanadu/xspec/walkthrough.tar.gz\n", 30 | "\n", 31 | "Read in the source and background spectra as separate files. \n" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "name": "stdout", 41 | "output_type": "stream", 42 | "text": [ 43 | "/Users/karnaud/Jupyter-notebooks/data\n", 44 | "\n", 45 | "2 spectra in use\n", 46 | " \n", 47 | "Spectral Data File: hisum.pha Spectrum 1\n", 48 | "Net count rate (cts/s) for Spectrum:1 1.371e+03 +/- 3.123e+00\n", 49 | " Assigned to Data Group 1 and Plot Group 1\n", 50 | " Noticed Channels: 1-48\n", 51 | " Telescope: GINGA Instrument: LAC Channel Type: PHA\n", 52 | " Exposure Time: 1 sec\n", 53 | " Using fit statistic: chi\n", 54 | " Using Response (RMF) File ginga_lac.rsp for Source 1\n", 55 | "\n", 56 | "Spectral Data File: losum.pha Spectrum 2\n", 57 | "Net count rate (cts/s) for Spectrum:2 1.401e+02 +/- 3.549e-01\n", 58 | " Assigned to Data Group 2 and Plot Group 2\n", 59 | " Noticed Channels: 1-48\n", 60 | " Telescope: GINGA Instrument: LAC Channel Type: PHA\n", 61 | " Exposure Time: 1 sec\n", 62 | " Using fit statistic: chi\n", 63 | " Using Response (RMF) File ginga_lac.rsp for Source 1\n", 64 | "\n", 65 | "Response successfully loaded.\n", 66 | "Response successfully loaded.\n" 67 | ] 68 | } 69 | ], 70 | "source": [ 71 | "%cd data\n", 72 | "AllData(\"1:1 hisum.pha 2:2 losum.pha\")\n", 73 | "s1 = AllData(1)\n", 74 | "s2 = AllData(2)\n", 75 | "s1.response = \"ginga_lac.rsp\"\n", 76 | "s2.response = \"ginga_lac.rsp\"" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "Set up the model for the source. Here we will take the simple case of an absorbed power-law and set the model normalization to zero for the background spectrum. " 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 3, 89 | "metadata": { 90 | "scrolled": true 91 | }, 92 | "outputs": [ 93 | { 94 | "name": "stdout", 95 | "output_type": "stream", 96 | "text": [ 97 | "\n", 98 | "========================================================================\n", 99 | "Model phabs<1>*powerlaw<2> Source No.: 1 Active/On\n", 100 | "Model Model Component Parameter Unit Value\n", 101 | " par comp\n", 102 | " Data group: 1\n", 103 | " 1 1 phabs nH 10^22 1.00000 +/- 0.0 \n", 104 | " 2 2 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 105 | " 3 2 powerlaw norm 1.00000 +/- 0.0 \n", 106 | " Data group: 2\n", 107 | " 4 1 phabs nH 10^22 1.00000 = p1\n", 108 | " 5 2 powerlaw PhoIndex 1.00000 = p2\n", 109 | " 6 2 powerlaw norm 1.00000 = p3\n", 110 | "________________________________________________________________________\n", 111 | "\n", 112 | "\n", 113 | "Fit statistic : Chi-Squared 2.214313e+07 using 48 bins.\n", 114 | " Chi-Squared 3.817637e+08 using 48 bins.\n", 115 | "Total fit statistic 4.039068e+08 with 93 d.o.f.\n", 116 | "\n", 117 | "Test statistic : Chi-Squared 4.039068e+08 using 96 bins.\n", 118 | " Null hypothesis probability of 0.000000e+00 with 93 degrees of freedom\n", 119 | " Current data and model not fit yet.\n", 120 | "\n", 121 | "Fit statistic : Chi-Squared 2.214313e+07 using 48 bins.\n", 122 | " Chi-Squared 177171.1 using 48 bins.\n", 123 | "Total fit statistic 2.232030e+07 with 93 d.o.f.\n", 124 | "\n", 125 | "Test statistic : Chi-Squared 2.232030e+07 using 96 bins.\n", 126 | " Null hypothesis probability of 0.000000e+00 with 93 degrees of freedom\n", 127 | " Current data and model not fit yet.\n" 128 | ] 129 | } 130 | ], 131 | "source": [ 132 | "Model(\"phabs * pow\")\n", 133 | "m1 = AllModels(1)\n", 134 | "m2 = AllModels(2)\n", 135 | "m2(3).values = \"0.0,-1.0\"" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "Now we need to set up the background model for both datasets with the appropriate response matrices. " 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 4, 148 | "metadata": {}, 149 | "outputs": [ 150 | { 151 | "name": "stdout", 152 | "output_type": "stream", 153 | "text": [ 154 | "Response successfully loaded.\n", 155 | "\n", 156 | "Fit statistic : Chi-Squared 2.214313e+07 using 48 bins.\n", 157 | " Chi-Squared 177171.1 using 48 bins.\n", 158 | "Total fit statistic 2.232030e+07 with 93 d.o.f.\n", 159 | "\n", 160 | "Test statistic : Chi-Squared 2.232030e+07 using 96 bins.\n", 161 | " Null hypothesis probability of 0.000000e+00 with 93 degrees of freedom\n", 162 | " Current data and model not fit yet.\n", 163 | "Response successfully loaded.\n", 164 | "\n", 165 | "Fit statistic : Chi-Squared 2.214313e+07 using 48 bins.\n", 166 | " Chi-Squared 177171.1 using 48 bins.\n", 167 | "Total fit statistic 2.232030e+07 with 93 d.o.f.\n", 168 | "\n", 169 | "Test statistic : Chi-Squared 2.232030e+07 using 96 bins.\n", 170 | " Null hypothesis probability of 0.000000e+00 with 93 degrees of freedom\n", 171 | " Current data and model not fit yet.\n" 172 | ] 173 | } 174 | ], 175 | "source": [ 176 | "s1.multiresponse[1] = \"ginga_lac.rsp\"\n", 177 | "s2.multiresponse[1] = \"ginga_lac.rsp\"" 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "This tells XSPEC that both these datasets have a second model which must be multiplied by the appropriate response matrix for its contribution to the source region and for its contribution to the background region. This is likely to be the case for a standard imaging data where the response will only depend on the extraction region. Note that for a coded-aperture mask the situation may be more complicated with a different response for the source and the background even if they are extracted from the same region of the detector. We now define the background model to be used. In this case take the simple example of a single power-law " 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 5, 190 | "metadata": {}, 191 | "outputs": [ 192 | { 193 | "name": "stdout", 194 | "output_type": "stream", 195 | "text": [ 196 | "\n", 197 | "========================================================================\n", 198 | "Model myback:powerlaw<1> Source No.: 2 Active/On\n", 199 | "Model Model Component Parameter Unit Value\n", 200 | " par comp\n", 201 | " Data group: 1\n", 202 | " 1 1 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 203 | " 2 1 powerlaw norm 1.00000 +/- 0.0 \n", 204 | " Data group: 2\n", 205 | " 3 1 powerlaw PhoIndex 1.00000 = myback:p1\n", 206 | " 4 1 powerlaw norm 1.00000 = myback:p2\n", 207 | "________________________________________________________________________\n", 208 | "\n", 209 | "\n", 210 | "Fit statistic : Chi-Squared 9.779387e+07 using 48 bins.\n", 211 | " Chi-Squared 4.523427e+08 using 48 bins.\n", 212 | "Total fit statistic 5.501366e+08 with 91 d.o.f.\n", 213 | "\n", 214 | "Test statistic : Chi-Squared 5.501366e+08 using 96 bins.\n", 215 | " Null hypothesis probability of 0.000000e+00 with 91 degrees of freedom\n", 216 | " Current data and model not fit yet.\n" 217 | ] 218 | } 219 | ], 220 | "source": [ 221 | "m1_2 = Model(\"pow\",\"myback\",2)" 222 | ] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "metadata": {}, 227 | "source": [ 228 | "We have now set up XSPEC so that the source data is compared to a source model multiplied by the source response plus a background model multiplied by the background response and the background data is compared to the background model multiplied by the background response. The background models fitted to the source and background data are constrained to be the same. " 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": 6, 234 | "metadata": {}, 235 | "outputs": [ 236 | { 237 | "name": "stdout", 238 | "output_type": "stream", 239 | "text": [ 240 | "\n", 241 | "Parameters defined:\n", 242 | "========================================================================\n", 243 | "Model phabs<1>*powerlaw<2> Source No.: 1 Active/On\n", 244 | "Model Model Component Parameter Unit Value\n", 245 | " par comp\n", 246 | " Data group: 1\n", 247 | " 1 1 phabs nH 10^22 1.00000 +/- 0.0 \n", 248 | " 2 2 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 249 | " 3 2 powerlaw norm 1.00000 +/- 0.0 \n", 250 | " Data group: 2\n", 251 | " 4 1 phabs nH 10^22 1.00000 = p1\n", 252 | " 5 2 powerlaw PhoIndex 1.00000 = p2\n", 253 | " 6 2 powerlaw norm 0.0 frozen\n", 254 | "________________________________________________________________________\n", 255 | "\n", 256 | "========================================================================\n", 257 | "Model myback:powerlaw<1> Source No.: 2 Active/On\n", 258 | "Model Model Component Parameter Unit Value\n", 259 | " par comp\n", 260 | " Data group: 1\n", 261 | " 1 1 powerlaw PhoIndex 1.00000 +/- 0.0 \n", 262 | " 2 1 powerlaw norm 1.00000 +/- 0.0 \n", 263 | " Data group: 2\n", 264 | " 3 1 powerlaw PhoIndex 1.00000 = myback:p1\n", 265 | " 4 1 powerlaw norm 1.00000 = myback:p2\n", 266 | "________________________________________________________________________\n", 267 | "\n" 268 | ] 269 | } 270 | ], 271 | "source": [ 272 | "AllModels.show()" 273 | ] 274 | }, 275 | { 276 | "cell_type": "code", 277 | "execution_count": null, 278 | "metadata": {}, 279 | "outputs": [], 280 | "source": [] 281 | } 282 | ], 283 | "metadata": { 284 | "kernelspec": { 285 | "display_name": "Python 3 (ipykernel)", 286 | "language": "python", 287 | "name": "python3" 288 | }, 289 | "language_info": { 290 | "codemirror_mode": { 291 | "name": "ipython", 292 | "version": 3 293 | }, 294 | "file_extension": ".py", 295 | "mimetype": "text/x-python", 296 | "name": "python", 297 | "nbconvert_exporter": "python", 298 | "pygments_lexer": "ipython3", 299 | "version": "3.12.6" 300 | } 301 | }, 302 | "nbformat": 4, 303 | "nbformat_minor": 4 304 | } 305 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyXspec-Jupyter-notebooks 2 | A collection of Jupyter notebooks illustrating [PyXspec](https://heasarc.gsfc.nasa.gov/docs/xanadu/xspec/) analysis 3 | 4 | The PyXspecWalkthroughN notebooks are for the examples in the Walks through XSPEC section of the manual. Those whose names include Matplotlib use matplotlib to do the plotting while the others use the native XSPEC plotting using the pgplot svg driver. 5 | 6 | A brief summary for each N in PyXspecWalkthroughN is: 7 | 8 | 1 - Fitting Models to Data: An Old Example from EXOSAT 9 | 10 | 2 - Simultaneous Fitting 11 | 12 | 3 - Multiple Models: a Background Modeling Example 13 | 14 | 4 - Using XSPEC to Simulate Data: an Example for Chandra 15 | 16 | 5 - Producing Plots: Modifying the Defaults 17 | 18 | PyXspecIXPEPolarPlot is an example using IXPE data which makes a contour plot in polar coordinates. 19 | 20 | These notebooks assume XSPEC v12.12 or later. 21 | -------------------------------------------------------------------------------- /data/aciss.fak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/aciss.fak -------------------------------------------------------------------------------- /data/aciss_aimpt_cy15.arf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/aciss_aimpt_cy15.arf -------------------------------------------------------------------------------- /data/aciss_aimpt_cy15.rmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/aciss_aimpt_cy15.rmf -------------------------------------------------------------------------------- /data/det1_filt_src.arf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det1_filt_src.arf -------------------------------------------------------------------------------- /data/det1_filt_src.mrf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det1_filt_src.mrf -------------------------------------------------------------------------------- /data/det1_filt_src_I.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det1_filt_src_I.pha -------------------------------------------------------------------------------- /data/det1_filt_src_Q.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det1_filt_src_Q.pha -------------------------------------------------------------------------------- /data/det1_filt_src_U.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det1_filt_src_U.pha -------------------------------------------------------------------------------- /data/det2_filt_src.arf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det2_filt_src.arf -------------------------------------------------------------------------------- /data/det2_filt_src.mrf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det2_filt_src.mrf -------------------------------------------------------------------------------- /data/det2_filt_src_I.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det2_filt_src_I.pha -------------------------------------------------------------------------------- /data/det2_filt_src_Q.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det2_filt_src_Q.pha -------------------------------------------------------------------------------- /data/det2_filt_src_U.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det2_filt_src_U.pha -------------------------------------------------------------------------------- /data/det3_filt_src.arf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det3_filt_src.arf -------------------------------------------------------------------------------- /data/det3_filt_src.mrf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det3_filt_src.mrf -------------------------------------------------------------------------------- /data/det3_filt_src_I.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det3_filt_src_I.pha -------------------------------------------------------------------------------- /data/det3_filt_src_Q.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det3_filt_src_Q.pha -------------------------------------------------------------------------------- /data/det3_filt_src_U.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/det3_filt_src_U.pha -------------------------------------------------------------------------------- /data/ginga_lac.rsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/ginga_lac.rsp -------------------------------------------------------------------------------- /data/hisum.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/hisum.pha -------------------------------------------------------------------------------- /data/ixpe_d1_20170101_alpha075_02.rmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/ixpe_d1_20170101_alpha075_02.rmf -------------------------------------------------------------------------------- /data/ixpe_d2_20170101_alpha075_02.rmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/ixpe_d2_20170101_alpha075_02.rmf -------------------------------------------------------------------------------- /data/ixpe_d3_20170101_alpha075_02.rmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/ixpe_d3_20170101_alpha075_02.rmf -------------------------------------------------------------------------------- /data/losum.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/losum.pha -------------------------------------------------------------------------------- /data/pgplot.svg: -------------------------------------------------------------------------------- 1 | 7 | 19 | 20 |  XSPEC version: 12.12.0a_d 21 | Build Date/Time: Thu Sep  9 13:09:02 2021 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /data/s54405.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/s54405.pha -------------------------------------------------------------------------------- /data/s54405.rsp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/s54405.rsp -------------------------------------------------------------------------------- /data/test.fak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/test.fak -------------------------------------------------------------------------------- /data/test1.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/data/test1.fits -------------------------------------------------------------------------------- /pyxspecTutorials/PyXspec-TheExtendedTutorial.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 142, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "#\n", 12 | "# some standard python imports\n", 13 | "#\n", 14 | "\n", 15 | "%matplotlib inline\n", 16 | "\n", 17 | "import matplotlib\n", 18 | "import numpy as np\n", 19 | "import matplotlib.pyplot as plt\n", 20 | "\n", 21 | "import xspec # this imports the xspec package \n", 22 | "\n", 23 | "xspec.Xset.allowPrompting = False # keeps pyxspec from hanging, waiting for a response to a prompt\n" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "----\n", 31 | "\n", 32 | "## Data\n", 33 | "\n", 34 | "### Background, Response, and Arf\n", 35 | "\n", 36 | "When a Spectrum object is created from a spectral data file, PyXspec also reads the file's BACKFILE, RESPFILE, and ANCRFILE keywords and will load the corresponding background, response, and arf files. The spectrum's Background and Response objects are then available as attributes of the Spectrum class, while the arf file name becomes an attribute of the Response class. Note that you never create Background and Response objects directly. They are accessible only through the Spectrum class attributes.\n", 37 | "\n" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 143, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "s1 = xspec.Spectrum(\"data/spec\")\n", 47 | "try:\n", 48 | " b1 = s1.background\n", 49 | "except Exception:\n", 50 | " b1 = ''\n", 51 | "b1='' # spectrum has no background\n", 52 | "try: \n", 53 | " r1 = s1.response\n", 54 | "except Exception:\n", 55 | " r1='' # no response defined\n", 56 | "try:\n", 57 | " arfFileName = r1.arf\n", 58 | "except Exception:\n", 59 | " arfFileName = '' # no arf defined either" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "Use these attributes if you need to add or change a response, arf or background file, for example:" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 144, 72 | "metadata": {}, 73 | "outputs": [ 74 | { 75 | "name": "stdout", 76 | "output_type": "stream", 77 | "text": [ 78 | "New background = data/spec_bkg.pha\n", 79 | "New Response = data/spec.rmf\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "# Add a background files:\n", 85 | "\n", 86 | "if not b1:\n", 87 | " s1.background = \"data/spec_bkg.pha\"\n", 88 | " print \"New background = {0}\".format(s1.background.fileName)\n", 89 | "\n", 90 | "# Add a response\n", 91 | "if not r1:\n", 92 | " s1.response = \"data/spec.rmf\"\n", 93 | " print \"New Response = {0}\".format(s1.response.rmf)\n", 94 | "\n" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 19, 100 | "metadata": {}, 101 | "outputs": [ 102 | { 103 | "data": { 104 | "text/plain": [ 105 | "'data/spec.rmf'" 106 | ] 107 | }, 108 | "execution_count": 19, 109 | "metadata": {}, 110 | "output_type": "execute_result" 111 | } 112 | ], 113 | "source": [ 114 | "s1.response.rmf" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "#### To add an ARF:\n", 122 | "\n", 123 | "`s1.response.arf = \"newArf.pha\"`\n", 124 | "\n", 125 | "#### To remove backgrounds, etc:\n", 126 | "\n", 127 | "```\n", 128 | "s1.response = None\n", 129 | "s1.background = \"\"\n", 130 | "```\n", 131 | "\n", 132 | "Background and Spectrum files store their original file names in their `fileName` attribute. This means that while you SET the Spectrum.background object by assigning it a file name (as shown above), to GET the file name you must access its fileName attribute, as shown above.\n", 133 | "\n", 134 | "Response stores its RMF and optional ARF file names in its `rmf` and `arf` attributes respectively.\n", 135 | "\n", 136 | "```\n", 137 | "rmfFileName = r1.rmf\n", 138 | "arfFileName = r1.arf\n", 139 | "```\n", 140 | "\n", 141 | "Background objects have some of the same attributes as Spectrum objects, such as areaScale, exposure, energies, and values. The Spectrum object's values array (actually a tuple) does NOT include contributions from the background. Those are stored separately in the associated Background object. *Please see the Classes reference guide or call the Python help function for the full class descriptions.*\n", 142 | "\n", 143 | "The Spectrum class also provides a multiresponse array attribute for assigning multiple detectors (or sources) to a spectrum. The standard 0-based Python array indices corresponding to the 1-based XSPEC source numbers:\n", 144 | "\n", 145 | "```\n", 146 | "# Set a response for source 2\n", 147 | "s1.multiresponse[1] = \"resp2.rsp\"\n", 148 | "# Get the response object for source 2\n", 149 | "r2 = s1.multiresponse[1]\n", 150 | "# Remove the response from source 2\n", 151 | "s1.multiresponse[1] = None\n", 152 | "# This is the same as doing s1.response = \"resp1.rsp\"\n", 153 | "s1.multiresponse[0] = \"resp1.rsp\"\n", 154 | "\n", 155 | "```\n", 156 | "\n", 157 | "The rule is: when doing single-source analysis (typical of most XSPEC sessions) use the response attribute, otherwise use the multiresponse array.\n", 158 | "\n", 159 | "----\n", 160 | "### Ignore/Notice\n", 161 | "\n", 162 | "To ignore channels for a SINGLE spectrum, call the Spectrum object's ignore method passing a string following the same syntax as for Standard XSPEC's ignore command:\n", 163 | "\n", 164 | "\n" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": 43, 170 | "metadata": {}, 171 | "outputs": [ 172 | { 173 | "name": "stdout", 174 | "output_type": "stream", 175 | "text": [ 176 | "Noticed Channels:\n", 177 | "6 7 8 9 10 11 12 13 14 15 16 17 18 19 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49\n" 178 | ] 179 | } 180 | ], 181 | "source": [ 182 | "s1.ignore(\"20-30\") # ignore channels 20 to 30 and all channels above 50 keV\n", 183 | "s1.ignore(\"**-5\")\n", 184 | "print \"Noticed Channels:\"\n", 185 | "for no in s1.noticed:\n", 186 | " print no,\n" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "Similarly, to notice channels in a single spectrum:" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": 44, 199 | "metadata": {}, 200 | "outputs": [ 201 | { 202 | "name": "stdout", 203 | "output_type": "stream", 204 | "text": [ 205 | "Noticed Channels:\n", 206 | "6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49\n" 207 | ] 208 | } 209 | ], 210 | "source": [ 211 | "s1.notice(\"20-25\")\n", 212 | "# s1.notice(\"all\")\n", 213 | "print \"Noticed Channels:\"\n", 214 | "for no in s1.noticed:\n", 215 | " print no,\n" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "As with Standard XSPEC, if the x-axis plot units are set to energies or wavelengths, ignore and notice will accept floating-point input assumed to be in those same units:\n", 223 | "\n", 224 | "```\n", 225 | "# Ignore channel bins corresponding to 15.0 to 20.0 nm wavelengths:\n", 226 | "Plot.xAxis = \"nm\"\n", 227 | "s1.ignore(\"15.-20.\")\n", 228 | "```\n", 229 | "\n", 230 | "The currently noticed channel ranges are displayed for each spectrum in the AllData.show() output. You can also get a list of the individual noticed channel numbers from Spectrum's noticed attribute, as shown above.\n", 231 | "\n", 232 | "\n", 233 | "To apply ignore and notice commands to ALL loaded spectra, call the methods from the global AllData object. To apply to a subset of loaded spectra, add a range specifier to the left of the colon:\n", 234 | "\n", 235 | "```\n", 236 | "# These apply to all loaded spectra\n", 237 | "AllData.ignore(\"100-120, 150-200\")\n", 238 | "AllData.notice(\"all\")\n", 239 | "AllData.ignore(\"bad\")\n", 240 | "# These apply to a subset of loaded spectra\n", 241 | "AllData.ignore(\"1-3: 60-65\")\n", 242 | "AllData.notice(\"2-**:50-60\")\n", 243 | "```\n", 244 | "\n" 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "metadata": {}, 250 | "source": [ 251 | "----\n", 252 | "\n", 253 | "### Models\n", 254 | "\n", 255 | "#### Model With Multiple Data Groups\n", 256 | "\n", 257 | "When a model is defined and spectra are assigned to multiple data groups, PyXspec will generate a Model object copy for each data group (assuming the spectra also have responses attached). So if:\n" 258 | ] 259 | }, 260 | { 261 | "cell_type": "code", 262 | "execution_count": 67, 263 | "metadata": {}, 264 | "outputs": [], 265 | "source": [ 266 | "#\n", 267 | "# Load 2 spectra, spec.pha and spec_sim.pha, into 2 separate data groups\n", 268 | "#\n", 269 | "xspec.AllData.clear()\n", 270 | "xspec.AllData += \"data/spec.pha\" # read spectrum into first data group\n", 271 | "# Explicitly specify the response if necessary\n", 272 | "xspec.AllData(1).response = \"data/spec.rmf\" # this response include the effective area (ARF) information\n", 273 | "\n", 274 | "xspec.AllData(\"2:2 data/spec_sim.pha\") # read spectrum into data group 2\n", 275 | "# Explicitly specify the response, if necessary\n", 276 | "xspec.AllData(2).response = \"data/spec3.rmf\" # response includes the ARF already\n", 277 | "\n", 278 | "m1 = xspec.Model(\"tbabs*pow\")\n", 279 | "m2 = xspec.AllModels(2)\n", 280 | "\n" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "then there are 2 Model objects for the model definition `tbabs*pow`. The variable `m1` is set to the object belonging to data group 1, and `m2` the object for data group 2, and `m1` and `m2` will each have the same set of Component and Parameter objects.\n" 288 | ] 289 | }, 290 | { 291 | "cell_type": "markdown", 292 | "metadata": {}, 293 | "source": [ 294 | "Parameters can be accessed directly by index from the Model objects, and these indices are numbered from 1 to nParameters for ALL data group copies. So for the \"Tbabs*pow\" example above:\n", 295 | "\n", 296 | "```\n", 297 | "p = m1(2) # Returns the 2nd parameter from m1, the model for data group 1.\n", 298 | "p = m2(2) # Returns the 2nd parameter from m2, the model for data group 2. \n", 299 | "```\n", 300 | "\n", 301 | "#### Defining Multiple Models\n", 302 | "\n", 303 | "Beginning with XSPEC12, it became possible to assign multiple sources to spectra, and each source may have its own model function definition. To keep track of multiple model definitions, XSPEC requires that you assign them names. In PyXspec, the model name and source number are supplied as additional arguments to the Model __init__ function.\n", 304 | "\n", 305 | "As with Standard XSPEC, to define a model for source numbers > 1 you first must load a detector response for the source. See \"Background, Response, and Arf\" in the previous section.\n", 306 | "\n", 307 | "\n" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 80, 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [ 316 | "xspec.AllData.clear() # clear previously loaded data\n", 317 | "s1 = xspec.Spectrum(\"data/spec\")\n", 318 | "# Set a response for source 2\n", 319 | "s1.multiresponse[1] = \"data/spec.rmf\"\n", 320 | "# Define a model named \"alpha\" assigned to source 1\n", 321 | "m_1_1 = xspec.Model(\"wa*po\",\"alpha\")\n", 322 | "# Define a model named \"beta\" assigned to source 2\n", 323 | "m_2_1 = xspec.Model(\"tbabs*po\",\"beta\", sourceNum=2)\n", 324 | "# (In both of these cases, the returned object belongs to data group 1)\n" 325 | ] 326 | }, 327 | { 328 | "cell_type": "markdown", 329 | "metadata": {}, 330 | "source": [ 331 | "Note that in all previous examples in this tutorial, we have been using unnamed models which were assigned to source 1. Named models and source numbers may also be defined directly into the AllModels container by passing in a tuple:\n", 332 | "\n" 333 | ] 334 | }, 335 | { 336 | "cell_type": "code", 337 | "execution_count": 89, 338 | "metadata": {}, 339 | "outputs": [], 340 | "source": [ 341 | "xspec.AllModels.clear() # clear previous models\n", 342 | "# Define a model named \"defn1\" assigned to source 1\n", 343 | "xspec.AllModels += (\"wa*po\", \"defn1\")\n", 344 | "# Define a model named \"defn2\" assigned to source 2\n", 345 | "xspec.AllModels += (\"const*bbody\", \"defn2\", 2)\n", 346 | "# This replaces \"defn1\" with an unnamed model for source 1\n", 347 | "xspec.AllModels += \"wa*gaussian\"\n", 348 | "\n" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "and from which Model objects can be retrieved:" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": 106, 361 | "metadata": {}, 362 | "outputs": [ 363 | { 364 | "name": "stdout", 365 | "output_type": "stream", 366 | "text": [ 367 | "Model applied to data group 1, source 1='wabs*powerlaw'; Model applied to data group 2, source 2='constant*bbody'\n" 368 | ] 369 | } 370 | ], 371 | "source": [ 372 | "#\n", 373 | "# Load 2 spectra, spec.pha and spec_sim.pha, into 2 separate data groups\n", 374 | "#\n", 375 | "xspec.AllData.clear()\n", 376 | "s1 = xspec.Spectrum(\"data/spec\")\n", 377 | "# Set a response for source 2\n", 378 | "xspec.AllData(1).response = \"data/spec.rmf\" # this response include the effective area (ARF) information\n", 379 | "s1.multiresponse[1] = \"data/spec.rmf\"\n", 380 | "\n", 381 | "xspec.AllData(\"2:2 data/spec_sim.pha\") # read spectrum into data group 2\n", 382 | "# Explicitly specify the response, if necessary\n", 383 | "xspec.AllData(2).response = \"data/spec3.rmf\" # response includes the ARF already\n", 384 | "s2=xspec.AllData(2)\n", 385 | "s2.multiresponse[1] = \"data/spec3.rmf\"\n", 386 | "\n", 387 | "xspec.AllModels.clear() # clear previous models\n", 388 | "xspec.AllModels += (\"wa*po\", \"defn1\") # Define a model named \"defn1\" assigned to source 1\n", 389 | "xspec.AllModels += (\"const*bbody\", \"defn2\", 2) # Define a model named \"defn2\" assigned to source 2\n", 390 | "\n", 391 | "\n", 392 | "# Get the \"defn2\" Model object for data group 1\n", 393 | "m_2_1 = xspec.AllModels(1,\"defn1\")\n", 394 | "# ...and for data group 2\n", 395 | "m_2_2 = xspec.AllModels(2,\"defn2\")\n", 396 | "\n", 397 | "\n", 398 | "print \"Model applied to data group 1, source 1='{0}'; Model applied to data group 2, source 2='{1}'\".format(m_2_1.expression, m_2_2.expression)" 399 | ] 400 | }, 401 | { 402 | "cell_type": "markdown", 403 | "metadata": {}, 404 | "source": [ 405 | "To view all current source number and model assignments, see the AllModels.sources attribute, which displays a dictionary of the [source number]:[model name] pairs:\n", 406 | "\n" 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": 107, 412 | "metadata": {}, 413 | "outputs": [ 414 | { 415 | "data": { 416 | "text/plain": [ 417 | "{1: 'defn1', 2: 'defn2'}" 418 | ] 419 | }, 420 | "execution_count": 107, 421 | "metadata": {}, 422 | "output_type": "execute_result" 423 | } 424 | ], 425 | "source": [ 426 | "xspec.AllModels.sources" 427 | ] 428 | }, 429 | { 430 | "cell_type": "markdown", 431 | "metadata": {}, 432 | "source": [ 433 | "To remove model definitions:" 434 | ] 435 | }, 436 | { 437 | "cell_type": "code", 438 | "execution_count": 108, 439 | "metadata": {}, 440 | "outputs": [], 441 | "source": [ 442 | "# Remove all data group copies of \"defn2\"\n", 443 | "xspec.AllModels -= \"defn2\"\n", 444 | "# Remove all data group copies of the unnamed model (defined above as \"wa*gaussian\")\n", 445 | "#xspec.AllModels -= \"\"\n", 446 | "# Remove all copies of ALL model definitions\n", 447 | "xspec.AllModels.clear()\n", 448 | "\n" 449 | ] 450 | }, 451 | { 452 | "cell_type": "markdown", 453 | "metadata": {}, 454 | "source": [ 455 | "#### Component And Parameter Access Part 2\n", 456 | "\n", 457 | "When PyXspec constructs a Model object, it immediately adds to it an attribute of type Component for every component in the model expression. The attribute has the same (full) name as the component in the original expression, allowing you to access it as:\n", 458 | "\n", 459 | "\n" 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": 112, 465 | "metadata": {}, 466 | "outputs": [ 467 | { 468 | "data": { 469 | "text/plain": [ 470 | "'powerlaw'" 471 | ] 472 | }, 473 | "execution_count": 112, 474 | "metadata": {}, 475 | "output_type": "execute_result" 476 | } 477 | ], 478 | "source": [ 479 | "m = xspec.Model(\"wa*pow\")\n", 480 | "c2 = m.powerlaw\n", 481 | "c2.name" 482 | ] 483 | }, 484 | { 485 | "cell_type": "raw", 486 | "metadata": {}, 487 | "source": [ 488 | "\n", 489 | "However when a model contains multiple copies of the same component, this type of access becomes ambiguous. So to distinguish among copies, for any component making its 2nd or more appearance (from left to right), PyXspec will append \"_n\" to the attribute name where n refers to the component's position in the expression (again from left to right). For example:\n", 490 | "\n" 491 | ] 492 | }, 493 | { 494 | "cell_type": "code", 495 | "execution_count": 114, 496 | "metadata": {}, 497 | "outputs": [], 498 | "source": [ 499 | "m = xspec.Model(\"wa*po + po\")\n", 500 | "# This gets the leftmost powerlaw component\n", 501 | "pow1 = m.powerlaw\n", 502 | "# This gets the rightmost, which is the 3rd component in the expression.\n", 503 | "pow2 = m.powerlaw_3\n", 504 | "\n" 505 | ] 506 | }, 507 | { 508 | "cell_type": "markdown", 509 | "metadata": {}, 510 | "source": [ 511 | "\n", 512 | "The Model object also stores an attribute which is a just a list of the names of its constituent Component attributes:\n", 513 | "\n" 514 | ] 515 | }, 516 | { 517 | "cell_type": "code", 518 | "execution_count": 115, 519 | "metadata": {}, 520 | "outputs": [ 521 | { 522 | "data": { 523 | "text/plain": [ 524 | "['wabs', 'powerlaw', 'powerlaw_3']" 525 | ] 526 | }, 527 | "execution_count": 115, 528 | "metadata": {}, 529 | "output_type": "execute_result" 530 | } 531 | ], 532 | "source": [ 533 | "m.componentNames" 534 | ] 535 | }, 536 | { 537 | "cell_type": "markdown", 538 | "metadata": {}, 539 | "source": [ 540 | "This may be useful, for example, if writing a loop to access each of a model's components. Similarly `Component` objects have a `parameterNames` attribute, listing the names of their constituent Parameter attributes:\n" 541 | ] 542 | }, 543 | { 544 | "cell_type": "code", 545 | "execution_count": 117, 546 | "metadata": {}, 547 | "outputs": [ 548 | { 549 | "data": { 550 | "text/plain": [ 551 | "['PhoIndex', 'norm']" 552 | ] 553 | }, 554 | "execution_count": 117, 555 | "metadata": {}, 556 | "output_type": "execute_result" 557 | } 558 | ], 559 | "source": [ 560 | "m.powerlaw.parameterNames" 561 | ] 562 | }, 563 | { 564 | "cell_type": "markdown", 565 | "metadata": {}, 566 | "source": [ 567 | "#### Gain Parameters (Response Models)\n", 568 | "\n", 569 | "Response Models differ from the regular kind in that they act on a Response rather than directly calculating a flux. At present there is only one kind of Response Model in Xspec, and this is `gain`. `gain` is a built-in attribute of all Response objects, and is of the class type `RModel`. It has 2 parameters for adjusting the energies of a Response: slope and offset. Gain parameters are initially off by default, but may be turned on simply by setting either one. For example:" 570 | ] 571 | }, 572 | { 573 | "cell_type": "code", 574 | "execution_count": 126, 575 | "metadata": {}, 576 | "outputs": [ 577 | { 578 | "name": "stdout", 579 | "output_type": "stream", 580 | "text": [ 581 | "The offset is 0.03 and the slope is 0.99\n" 582 | ] 583 | } 584 | ], 585 | "source": [ 586 | "s = xspec.Spectrum(\"data/spec\")\n", 587 | "s.response = \"data/spec.rmf\"\n", 588 | "\n", 589 | "# The spectrum's response has a gain attribute that is not in use,\n", 590 | "# which is the equivalent of having a slope fixed at 1.0 and offset = 0.0.\n", 591 | "\n", 592 | "r = s.response\n", 593 | "# Setting either the slope or offset turns the gain on for this response.\n", 594 | "# Both slope and offset will now be fit parameters.\n", 595 | "r.gain.slope = 1.05\n", 596 | "# The previous setting leaves the offset at 0.0. Now we'll change it.\n", 597 | "r.gain.offset = .05\n", 598 | "# You can set slope and offset at the same time using Response's setPars method.\n", 599 | "r.setPars(.99, .03)\n", 600 | "\n", 601 | "print \"The offset is {0} and the slope is {1}\".format(s.response.gain.offset.values[0],s.response.gain.slope.values[0])" 602 | ] 603 | }, 604 | { 605 | "cell_type": "code", 606 | "execution_count": 127, 607 | "metadata": {}, 608 | "outputs": [], 609 | "source": [ 610 | "# Modify the parameter's auxilliary values\n", 611 | "r.gain.offset = \".08,,.01,.01,.5,.5\"\n", 612 | "# Set a parameter link\n", 613 | "r.gain.offset.link = \".005*1\"\n", 614 | "\n" 615 | ] 616 | }, 617 | { 618 | "cell_type": "markdown", 619 | "metadata": {}, 620 | "source": [ 621 | "To remove the response fit parameters and return the Response back to its original state, call the gain.off() method:\n", 622 | "\n" 623 | ] 624 | }, 625 | { 626 | "cell_type": "code", 627 | "execution_count": 128, 628 | "metadata": { 629 | "collapsed": true 630 | }, 631 | "outputs": [], 632 | "source": [ 633 | "# This deletes the slope and offset parameters.\n", 634 | "# Any references to them become invalid.\n", 635 | "r.gain.off()\n", 636 | "\n" 637 | ] 638 | }, 639 | { 640 | "cell_type": "markdown", 641 | "metadata": {}, 642 | "source": [ 643 | "### Flux Calculations\n", 644 | "\n", 645 | "To perform a Standard XSPEC flux or lumin calculation, call the AllModels methods calcFlux or calcLumin respectively:\n" 646 | ] 647 | }, 648 | { 649 | "cell_type": "code", 650 | "execution_count": 129, 651 | "metadata": { 652 | "collapsed": true 653 | }, 654 | "outputs": [], 655 | "source": [ 656 | "xspec.AllModels.calcFlux(\".3 1.0\")\n", 657 | "xspec.AllModels.calcFlux(\".1 10.0 err\")\n", 658 | "xspec.AllModels.calcLumin(\".1 10. .05 err\")\n" 659 | ] 660 | }, 661 | { 662 | "cell_type": "markdown", 663 | "metadata": {}, 664 | "source": [ 665 | "As in Standard XSPEC the results will be stored with the currently loaded spectra:" 666 | ] 667 | }, 668 | { 669 | "cell_type": "code", 670 | "execution_count": 133, 671 | "metadata": {}, 672 | "outputs": [ 673 | { 674 | "name": "stdout", 675 | "output_type": "stream", 676 | "text": [ 677 | "Flux = (2.861965511334301e-08, 0.0, 0.0, 6.341347715278822, 0.0, 0.0)\n", 678 | "Luminosity = (1604.845391020328, 0.0, 0.0, 6.2919213498135145, 0.0, 0.0)\n" 679 | ] 680 | } 681 | ], 682 | "source": [ 683 | "s1 = xspec.AllData(1)\n", 684 | "print 'Flux = ',s1.flux\n", 685 | "print 'Luminosity =',s1.lumin\n", 686 | "\n" 687 | ] 688 | }, 689 | { 690 | "cell_type": "markdown", 691 | "metadata": {}, 692 | "source": [ 693 | "unless there are no spectra, in which case the results are stored with the model object:\n", 694 | "\n" 695 | ] 696 | }, 697 | { 698 | "cell_type": "code", 699 | "execution_count": 136, 700 | "metadata": {}, 701 | "outputs": [ 702 | { 703 | "name": "stdout", 704 | "output_type": "stream", 705 | "text": [ 706 | "Model Flux - (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)\n" 707 | ] 708 | } 709 | ], 710 | "source": [ 711 | "xspec.AllData.clear()\n", 712 | "print \"Model Flux - \",xspec.AllModels(1).flux\n" 713 | ] 714 | }, 715 | { 716 | "cell_type": "markdown", 717 | "metadata": {}, 718 | "source": [ 719 | "----\n", 720 | "\n", 721 | "### Local Models in C/C++/Fortran\n", 722 | "\n", 723 | "In Standard XSPEC, local model libraries are built with the initpackage comamnd and then loaded with lmod. The AllModels container supplies both of these functions for doing the same thing in PyXspec:\n", 724 | "\n", 725 | "AllModels.initpackage(\"myLocalMods\",\"lmodel.dat\")\n", 726 | "AllModels.lmod(\"myLocalMods\")\n", 727 | "\n", 728 | "By default this looks in the directory set by the LOCAL_MODEL_DIRECTORY variable in your ~/.xspec/Xspec.init start-up file. You can override this by giving these functions an absolute or relative path as a dirPath keyword argument (see the Class guide for details).\n", 729 | "\n", 730 | "Local Models in Python\n", 731 | "\n", 732 | "You can also write model functions in Python and insert them into the XSPEC library with the AllModels addPyMod method. You simply define a function with 3 arguments for energies, parameters, and flux. For example a powerlaw model function might look like:\n" 733 | ] 734 | }, 735 | { 736 | "cell_type": "code", 737 | "execution_count": 137, 738 | "metadata": { 739 | "collapsed": true 740 | }, 741 | "outputs": [], 742 | "source": [ 743 | "def lpow(engs, params, flux):\n", 744 | " for i in range(len(engs)-1):\n", 745 | " pconst = 1.0 - params[0]\n", 746 | " val = math.pow(engs[i+1],pconst)/pconst - math.pow(engs[i],pconst)/pconst\n", 747 | " flux[i] = val\n", 748 | "\n" 749 | ] 750 | }, 751 | { 752 | "cell_type": "markdown", 753 | "metadata": {}, 754 | "source": [ 755 | "XSPEC will pass tuples containing the energy and parameter values to your function. For the flux array, it will pass a list pre-sized to nE-1, where nE is the size of the energies array. Your model function should fill in this list with the proper flux values. (For additional optional arguments to your model function, please see the documentation for the addPyMod function.)\n", 756 | "\n", 757 | "The second thing you must define is a tuple containing the parameters' information strings, one string for each parameter in your model. This is equivalent to the parameter strings you would define in a 'model.dat' file when adding local models in standard XSPEC, and it requires the same format. (See Appendix C of the XSPEC manual for more details.) So with the powerlaw function above which takes just 1 parameter, you might define a tuple as:\n", 758 | "\n", 759 | "`powInfo = (\"phoIndex \\\"\" 1.1 -3. -2. 9. 10. 0.01\",)`\n", 760 | "\n", 761 | "Note the need for the **trailing comma** when there's just one parameter string. This is to let Python know that powInfo is a tuple type and not a string.\n", 762 | "\n", 763 | "Once you've defined your function and parameter information, simply call:\n", 764 | "\n", 765 | "`AllModels.addPyMod(lpow, powInfo, 'add')`\n", 766 | "\n", 767 | "The 3rd argument tells XSPEC the type of your model function ('add', 'mul', or 'con'). After this call your function will be added to the list of available model components, which you can see by doing 'Model.showList()'. Your model will show up with the same name as your original Python function ('lpow'), and is ready for use in future Model definitions.\n", 768 | "\n", 769 | "\n" 770 | ] 771 | }, 772 | { 773 | "cell_type": "markdown", 774 | "metadata": {}, 775 | "source": [ 776 | "----\n", 777 | "\n", 778 | "### Fitting\n", 779 | "\n", 780 | "#### Error\n", 781 | "\n", 782 | "The error command is implemented through Fit, and the results are stored with the chosen Parameter object(s). The error attribute stores a tuple containing the low and high range values for the parameter, and the 9-letter status string to report problems incurred during the error calculation.\n", 783 | "\n", 784 | "```\n", 785 | "# Estimate the 90% confidence range for the 4th parameter\n", 786 | "xspec.Fit.error(\"2.706 4\")\n", 787 | "xspec.par4 = AllModels(1)(4)\n", 788 | "xspec.par4.error\n", 789 | "(0.11350354517707145, 0.14372981075906774, 'FFFFFFFFF')\n", 790 | "```" 791 | ] 792 | }, 793 | { 794 | "cell_type": "markdown", 795 | "metadata": {}, 796 | "source": [ 797 | "#### Query\n", 798 | "\n", 799 | "During an xspec.Fit.perform() operation, the default is to query the user whenever the fit has run the maximum number of iterations, as set by the Fit.nIterations attribute. You can change this behavior with the query attribute:\n" 800 | ] 801 | }, 802 | { 803 | "cell_type": "code", 804 | "execution_count": 140, 805 | "metadata": {}, 806 | "outputs": [], 807 | "source": [ 808 | "# When nIterations is reached, continue the fit without stopping to query.\n", 809 | "xspec.Fit.query = \"yes\"\n", 810 | "# Stop fit at nIterations and do not query.\n", 811 | "xspec.Fit.query = \"no\"\n", 812 | "# Query the user when nIterations is reached.\n", 813 | "xspec.Fit.query = \"on\"\n" 814 | ] 815 | }, 816 | { 817 | "cell_type": "markdown", 818 | "metadata": {}, 819 | "source": [ 820 | "\n", 821 | "#### Steppar\n", 822 | "\n", 823 | "The Standard XSPEC steppar command is also implemented through the global Fit object. You supply it with a string following the same steppar command syntax rules. For example:\n", 824 | "\n", 825 | "```\n", 826 | "# Step parameters 1 and 2 through the given range values\n", 827 | "# over a 10x10 2-D grid.\n", 828 | "Fit.steppar(\"1 20. 30. 10 2 .05 .08 10\")\n", 829 | "```\n", 830 | "\n", 831 | "### Fakeit\n", 832 | "\n", 833 | "PyXspec provides access to standard XSPEC's fakeit command, which is for creating spectra with simulated data. It is called through the AllData fakeit method:\n", 834 | "\n", 835 | "AllData.fakeit(nSpectra=1, settings=None, applyStats=True, filePrefix=\"\")\n", 836 | "\n", 837 | "NOTE: If AllData.fakeit is run when spectra are currently loaded, it will follow the same rules as the standard XSPEC fakeit function: It will REMOVE ALL pre-existing spectra and replace each one with a simulated spectrum (even if nSpectra is less than the number originally loaded).\n", 838 | "\n", 839 | "As those familiar with standard fakeit know, the user is normally prompted for quite a bit of additional information needed to generate the fakeit files. However the goal here is to have NO additional prompting, and that requires that all information must be entered as arguments to the AllData fakeit method call. This is done by passing objects of the FakeitSettings class to AllData.fakeit, as we'll show further below.\n", 840 | "\n", 841 | "NOTE: Unless stated otherwise, assume all spectra are OGIP type-1 (1 spectrum per file).\n", 842 | "\n", 843 | "For the simplest of cases, you don't need to create any FakeitSettings objects. Just pass in the number of fake spectra you'd like to create:\n", 844 | "\n" 845 | ] 846 | }, 847 | { 848 | "cell_type": "code", 849 | "execution_count": 141, 850 | "metadata": { 851 | "collapsed": true 852 | }, 853 | "outputs": [], 854 | "source": [ 855 | "# Create 3 fake spectra using only default settings.\n", 856 | "xspec.AllData.fakeit(3)" 857 | ] 858 | }, 859 | { 860 | "cell_type": "markdown", 861 | "metadata": {}, 862 | "source": [ 863 | "The fakeit function will then create a default `FakeitSettings` object for each of the 3 spectra. By default, a FakeitSettings object will have empty strings for all of its attributes, and these are handled differently depending on whether the fake spectrum is replacing a currently loaded spectrum, or creating one from scratch.\n", 864 | "\n", 865 | "#### From Existing Spectra\n", 866 | "\n", 867 | "When replacing an existing spectrum, FakeitSettings attributes with empty strings will simply take their value from the original spectrum. Also note that the response and arf settings for the original spectrum CANNOT be modified for the fakeit spectrum. If a name is filled in for either of these attributes, it will be ignored. If you wish to modify these, you can make the change to the original spectrum prior to calling fakeit. [The one exception is when the original spectrum has no response, in which case the response attribute MUST be filled in.] If the fileName attribute is empty, XSPEC will generate a default output name derived from the original file name.\n", 868 | "\n", 869 | "#### From Scratch\n", 870 | "\n", 871 | "When creating from scratch, an empty string implies \"none\" for the arf and background, 1.0 for exposure and correction, and XSPEC's default dummy response for the response attribute. If the fileName attribute is empty, XSPEC will generate a default output file name based on the response name, and it will include an auto-incremented index to prevent multiple output files from overwriting each other.\n", 872 | "\n", 873 | "FakeitSettings Objects\n", 874 | "\n", 875 | "To create a fake spectrum with anything other than default settings, you must supply a FakeitSettings object for that spectrum. The FakeitSettings attributes are: response, arf, background, exposure, correction, backExposure, and fileName. All are string types, though exposure, backExposure, and correction can also be entered as floats. Attributes can be set upon object construction, or anytime afterwards:\n", 876 | "\n", 877 | "fs1 = FakeitSettings(\"response1.rsp\", exposure = 1500.0)\n", 878 | "\n", 879 | "fs1.background = \"back1.pha\"\n", 880 | "\n", 881 | "A new FakeitSettings object can also be made by copying an existing one:\n", 882 | "\n", 883 | "fs2 = FakeitSettings(fs1)\n", 884 | "\n", 885 | "And now pass the objects to the fakeit method, either in a list, dictionary, or as a single object:\n", 886 | "\n", 887 | "```\n", 888 | "# Apply settings to fakeit spectra 1 and 2:\n", 889 | "AllData.fakeit(2,[fs1,fs2])\n", 890 | "# Apply setting to fakeit spectrum 1, use defaults for spectrum 2:\n", 891 | "AllData.fakeit(2, fs1)\n", 892 | "# Apply settings to fakeit spectra 2 and 4, use defaults for 1 and 3:\n", 893 | "settingsDict = {2:fs1, 4:fs2}\n", 894 | "AllData.fakeit(4, settingsDict)\n", 895 | "# Create 4 fakeit spectra from the same settings object:\n", 896 | "settingsList = 4*[fs1]\n", 897 | "AllData.fakeit(4, settingsList)\n", 898 | "```\n", 899 | "\n", 900 | "The remaining 2 arguments to the AllData.fakeit function are for choosing whether to apply statistical fluctuations (default = True), and whether to add an optional prefix string to the names of all output files.\n", 901 | "\n", 902 | "### OGIP Type-2 Files\n", 903 | "\n", 904 | "With OGIP type-2 files, multiple spectra may be placed in a single file. The important thing to recognize when generating type-2 fakeit files is that the exposure, correction, backExposure, and fileName attributes apply to the output files and not the individual spectra. Therefore these settings will be ignored for all but the first spectrum in a file. For example:\n", 905 | "\n", 906 | "```\n", 907 | "# Start with 4 spectra loaded, in 2 type-2 files:\n", 908 | "AllData(\"myDataFile1.pha{1-2} myDataFile2.pha{7-8}\")\n", 909 | "# Create settings for the 4 fake spectra that will be generated from these:\n", 910 | "fs1 = FakeitSettings(background=\"back1.pha\", exposure=250.) \n", 911 | "# The exposure setting in fs2 will be ignored!!!\n", 912 | "fs2 = FakeitSettings(background=\"back2.pha\", exposure 100.) \n", 913 | "fs3 = FakeitSettings(fileName=\"myFakeitFile_2.pha\")\n", 914 | "fs4 = FakeitSettings(fs3)\n", 915 | "# The following change will be ignored!!!\n", 916 | "fs4.fileName = \"myFakeitFile_3.pha\"\n", 917 | "# Now generate the fakeit files: AllData.fakeit(4, [fs1,fs2,fs3,fs4])\n", 918 | "```\n", 919 | "\n", 920 | "The above will generate 4 fakeit spectra, placed in 2 type-2 files. The exposure setting for spectrum 2 and the fileName setting for spectrum 4 will be ignored. Those values are only set by spectra 1 and 3.\n", 921 | "\n", 922 | "For more fakeit details and examples, please check:\n", 923 | "\n", 924 | "```\n", 925 | "help(FakeitSettings)\n", 926 | "help(DataManager.fakeit)\n", 927 | "```\n", 928 | "\n", 929 | "### Monte Carlo Markov Chains (MCMC)\n", 930 | "\n", 931 | "All MCMC operations are handled either by objects of class Chain, or the global AllChains container object. To create a new chain based on the current fit parameters, simply create a Chain object by passing it an output file name:\n", 932 | "\n", 933 | "`c1 = Chain(\"chain1.fits\")`\n", 934 | "\n", 935 | "The above call creates the file \"chain1.fits\", performs an MCMC run using the default burn, fileType, length, proposal, rand, and temperature values, and automatically places the new object in the AllChains container. These default settings are stored as attributes of AllChains:\n", 936 | "\n", 937 | "```\n", 938 | "# Ensure that new chains will burn the first 100 iterations, will\n", 939 | "# have length 1000, and will use the proposal \"gaussian fit\"\n", 940 | "AllChains.defBurn = 100\n", 941 | "AllChains.defLength = 1000\n", 942 | "AllChains.defProposal = \"gaussian fit\"\n", 943 | "c2 = Chain(\"chain2.fits\")\n", 944 | "```\n", 945 | "\n", 946 | "You can also override the AllChains default settings by passing additional arguments to Chain upon construction:\n", 947 | "\n", 948 | "```\n", 949 | "# Length will be 2000 for this chain, use defaults for all other settings.\n", 950 | "c3 = Chain(\"chain3.fits\", runLength = 2000)\n", 951 | "```\n", 952 | "\n", 953 | "The new chain objects will then store their own settings as attributes:\n", 954 | "\n", 955 | "```\n", 956 | "c2.burn\n", 957 | "100\n", 958 | "c2.runLength\n", 959 | "1000\n", 960 | "c3.runLength\n", 961 | "2000\n", 962 | "```\n", 963 | "\n", 964 | "All of a chain object's attributes will be displayed when calling its show() method.\n", 965 | "\n", 966 | "To append a new run to an existing chain object, call the object's run() method. The appending run will use the object's current attribute settings, and not the AllChains default settings:\n", 967 | "\n", 968 | "```\n", 969 | "# This will append a run of length 3000 to the c3 chain object, and with a\n", 970 | "# Metropolis-Hastings temperature of 50.0:\n", 971 | "c3.runLength = 3000\n", 972 | "c3.temperature = 50.0\n", 973 | "c3.run()\n", 974 | "\n", 975 | "c3.totalLength\n", 976 | "5000\n", 977 | "```\n", 978 | "To overwrite rather than append to an existing chain object, call run with its append argument set to False:\n", 979 | "\n", 980 | "```\n", 981 | "# This erases the results of any previous runs for object c3.\n", 982 | "c3.run(False)\n", 983 | "\n", 984 | "c3.totalLength\n", 985 | "3000\n", 986 | "```\n", 987 | "New chains are loaded into AllChains by default, but you can unload or reload them using the AllChains arithmetic operators:\n", 988 | "\n", 989 | "```\n", 990 | "# Chain c2 may be unloaded by passing its chain index number\n", 991 | "AllChains -= 2\n", 992 | "# OR by passing the object itself\n", 993 | "AllChains -= c2\n", 994 | "# 2 ways to remove ALL chains\n", 995 | "AllChains -= '*'\n", 996 | "AllChains.clear()\n", 997 | "\n", 998 | "\n", 999 | "# Reload an existing chain object\n", 1000 | "AllChains += c2\n", 1001 | "# Load a chain from an existing chain file\n", 1002 | "AllChains += \"earlierChain.fits\"\n", 1003 | "# Create a new chain, to be stored in file \"chain4.fits\"\n", 1004 | "AllChains += \"chain4.fits\"\n", 1005 | "```\n", 1006 | "\n", 1007 | "As with Standard XSPEC, unloading a chain will leave the chain's file intact. It merely removes the chain from XSPEC's calculations. To display information about the currently loaded chains, call AllChains.show().\n", 1008 | "\n", 1009 | "You may also get a chain object from the container at any time by passing it an index number:\n", 1010 | "\n", 1011 | "```\n", 1012 | "# Retrieve a chain object for the 4th chain in the container\n", 1013 | "c4 = AllChains(4)\n", 1014 | "```\n", 1015 | "\n", 1016 | "### Plotting\n", 1017 | "\n", 1018 | "All of the plotting options available in Standard XSPEC's setplot command are now implemented as attributes of the Plot object. Some of these are mentioned in the Quick Version of the tutorial, and please see the PlotManager class reference for the complete guide.\n", 1019 | "\n", 1020 | "One setting of particular interest is the commands attribute. This is a tuple of user-entered PLT command strings which are added to XSPEC's auto-generated commands when performing a plot, and is modified through Plot's addCommand and delCommand methods. For example, to enter a PLT command to place an additional label at the specified coordinates on the plot:\n", 1021 | "\n", 1022 | "`Plot.addCommand(\"label 1 pos 10 .05 \\\"Another Label\"\")`\n", 1023 | "\n", 1024 | "To view the currently loaded commands:\n", 1025 | "\n", 1026 | "`print Plot.commands`\n", 1027 | "\n", 1028 | "and to remove the 3rd command from the tuple:\n", 1029 | "\n", 1030 | "`Plot.delCommand(3)`\n", 1031 | "\n", 1032 | "### XSPEC Settings\n", 1033 | "\n", 1034 | "Most of the internal switches set through Standard XSPEC's xset command are now set through attributes of the global Xset object. Examples:\n", 1035 | "\n", 1036 | "```\n", 1037 | "Xset.abund = \"angr\"\n", 1038 | "Xset.cosmo = \"50 .5 0.\"\n", 1039 | "Xset.xsect = \"bcmc\"\n", 1040 | "```\n", 1041 | "\n", 1042 | "Xset also provides the methods `addModelString` and `delModelString` to set the `,` pairs which are used by certain models. The `` argument is case-insensitive.\n", 1043 | "\n", 1044 | "```\n", 1045 | "Xset.addModelString(\"APECROOT\",\"1.3.1\")\n", 1046 | "Xset.addModelString(\"APECTHERMAL\",\"yes\")\n", 1047 | "Xset.delModelString(\"neivers\")\n", 1048 | "```\n", 1049 | "\n", 1050 | "The entire collection of `,` pairs may be set or retrieved with the Xset.modelStrings attribute:\n", 1051 | "\n", 1052 | "```\n", 1053 | "# Replace all previous entries with a new dictionary\n", 1054 | "Xset.modelStrings = {\"neivers\":\"1.1\", \"apecroot\":\"1.3.1\"}\n", 1055 | "# Clear out all entries:\n", 1056 | "Xset.modelStrings = {}\n", 1057 | "```\n", 1058 | "\n", 1059 | "`Xset.show()` will display all of the current settings including the current `,` pairs.\n", 1060 | "\n", 1061 | "### Logging And XSPEC Output\n", 1062 | "\n", 1063 | "The Xset object provides attributes and methods for controlling output chatter level and for creating log files:\n", 1064 | "\n", 1065 | "```\n", 1066 | "# Get/Set the console chatter level\n", 1067 | "ch = Xset.chatter\n", 1068 | "Xset.chatter = 10\n", 1069 | "# Get/Set the log chatter level\n", 1070 | "lch = Xset.logChatter\n", 1071 | "Xset.logChatter = 20\n", 1072 | "\n", 1073 | "# Create and open a log file for XSPEC output\n", 1074 | "# This returns a Python file object\n", 1075 | "logFile = Xset.openLog(\"newLogFile.txt\")\n", 1076 | "# Get the Python file object for the currently opened log\n", 1077 | "logFile = Xset.log\n", 1078 | "# Close XSPEC's currently opened log file.\n", 1079 | "Xset.closeLog()\n", 1080 | "```\n", 1081 | "\n", 1082 | "### Exceptions And Error Handling\n", 1083 | "\n", 1084 | "PyXspec utilizes the standard Python try/except/raise mechanism for handling and reporting errors. In this early version, only exception objects of the class Exception are ever raised. In the future other (more specific) error classes may be used, but they should always be derived from Exception. So you can catch all PyXspec exceptions with code such as:\n", 1085 | "\n", 1086 | "```\n", 1087 | " try:\n", 1088 | " # Only 4 spectra are currently loaded\n", 1089 | " s = xspec.AllData(5)\n", 1090 | " except Exception, msg:\n", 1091 | " print msg \n", 1092 | "```\n", 1093 | "\n", 1094 | "which will print the error message:\n", 1095 | "\n", 1096 | "`Error: Spectrum index number is out of range: 5`\n", 1097 | "\n", 1098 | "PyXspec raises errors in a variety of situations, such as for invalid input argument syntax, or for input which is invalid within the context of the call (as in the example above). It can also raise exceptions if you try to rebind a class attribute when such modification is not permitted.\n", 1099 | "\n", 1100 | "### Adding Attributes To PyXspec Objects\n", 1101 | "\n", 1102 | "A particularly novel feature of Python (in comparison with say C++) is that it allows you to create new attributes \"on the fly\". The attributes don't have to have been part of the original class definition:\n", 1103 | "\n", 1104 | "```\n", 1105 | " class C:\n", 1106 | " pass\n", 1107 | "\n", 1108 | "\n", 1109 | " x = C()\n", 1110 | "x.pi = 3.1416\n", 1111 | "```\n", 1112 | "\n", 1113 | "The downside of course is that spelling or case sensitive errors become much harder to detect. For example, with PyXspec's Plot object:\n", 1114 | "\n", 1115 | "```\n", 1116 | "Plot.yLog = True # Correct\n", 1117 | "Plot.ylog = True # Wrong!\n", 1118 | "```\n", 1119 | "\n", 1120 | "In the second case, standard Python will simply add a new attribute named \"ylog\" to Plot, and this will have no effect on the actual plot since PyXspec is only looking at \"yLog\".\n", 1121 | "\n", 1122 | "So operating under the assumption that this downside outweighs the benefits, we've decided to disable the ability to add new attributes to PyXspec class objects. A misspelling or case error will instead raise an Exception object. And since some users may genuinely wish to add their own attributes to PyXspec classes, this default behavior may be overridden by toggling the Xset.allowNewAttributes flag:\n", 1123 | "\n", 1124 | "```\n", 1125 | "s = Spectrum(\"dataFile.pha\")\n", 1126 | "s.myNewIndex = 10 # Error: Will raise an exception\n", 1127 | "Xset.allowNewAttributes = True\n", 1128 | "s.myNewIndex = 10 # OK\n", 1129 | ".\n", 1130 | ". # Can add new attributes to any PyXspec object,\n", 1131 | ". # but attribute spelling errors will go undetected.\n", 1132 | ".\n", 1133 | "Xset.allowNewAttributes = False\n", 1134 | "```\n", 1135 | "\n", 1136 | "### Using With Other Packages\n", 1137 | "\n", 1138 | "One of the primary benefits of PyXspec is that it makes it much easier to use XSPEC data and results in 3rd party packages. For example you can bypass XSPEC's built-in plotting functions in favor of a Python plotting library such as Matplotlib:\n", 1139 | "\n", 1140 | "```\n", 1141 | "#!/usr/bin/python\n", 1142 | "\n", 1143 | "from xspec import *\n", 1144 | "import matplotlib.pyplot as plt\n", 1145 | "\n", 1146 | "# PyXspec operations:\n", 1147 | "s = Spectrum(\"file1.pha\")\n", 1148 | "m = Model(\"wa*po\")\n", 1149 | "Fit.perform()\n", 1150 | "\n", 1151 | "# Plot using Matplotlib:\n", 1152 | "plt.plot(s.noticed, s.values, 'ro', s.noticed, m.folded(1))\n", 1153 | "plt.xlabel('channels')\n", 1154 | "plt.ylabel('counts/cm^2/sec/chan')\n", 1155 | "plt.savefig('myplot')\n", 1156 | "```\n", 1157 | "\n", 1158 | "The above code produces a Matplotlib plot of the spectral data and folded model vs. channels (similar to what you get with Standard XSPEC's \"plot data\" command). It makes use of the Spectrum object's noticed attribute to pass a list of the channel numbers, and the values attribute (a tuple) to pass the spectral data values in counts/cm^2/s. The folded model values are obtained as a list by calling the Model object's folded method with a spectrum number argument." 1159 | ] 1160 | }, 1161 | { 1162 | "cell_type": "code", 1163 | "execution_count": null, 1164 | "metadata": { 1165 | "collapsed": true 1166 | }, 1167 | "outputs": [], 1168 | "source": [] 1169 | } 1170 | ], 1171 | "metadata": { 1172 | "kernelspec": { 1173 | "display_name": "Python 2", 1174 | "language": "python", 1175 | "name": "python2" 1176 | }, 1177 | "language_info": { 1178 | "codemirror_mode": { 1179 | "name": "ipython", 1180 | "version": 2 1181 | }, 1182 | "file_extension": ".py", 1183 | "mimetype": "text/x-python", 1184 | "name": "python", 1185 | "nbconvert_exporter": "python", 1186 | "pygments_lexer": "ipython2", 1187 | "version": "2.7.14" 1188 | }, 1189 | "nav_menu": {}, 1190 | "toc": { 1191 | "navigate_menu": true, 1192 | "number_sections": true, 1193 | "sideBar": true, 1194 | "threshold": 6, 1195 | "toc_cell": false, 1196 | "toc_section_display": "block", 1197 | "toc_window_display": true 1198 | } 1199 | }, 1200 | "nbformat": 4, 1201 | "nbformat_minor": 1 1202 | } 1203 | -------------------------------------------------------------------------------- /pyxspecTutorials/README.md: -------------------------------------------------------------------------------- 1 | # pyxspec-tutorial 2 | jupyter notebook version of the pxspec tutorials. The original pdf versions of the pyxspec tutorials can be found at 3 | 4 | https://heasarc.gsfc.nasa.gov/xanadu/xspec/python/html/quick.html 5 | 6 | and 7 | 8 | https://heasarc.gsfc.nasa.gov/xanadu/xspec/python/html/extended.html 9 | 10 | -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec.pha -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec.rmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec.rmf -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec2.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec2.pha -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec2_bkg.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec2_bkg.pha -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec3.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec3.pha -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec3.rmf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec3.rmf -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec3_bkg.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec3_bkg.pha -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec_bkg.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec_bkg.pha -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec_sim.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec_sim.pha -------------------------------------------------------------------------------- /pyxspecTutorials/data/spec_sim_bkg.pha: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HEASARC/PyXspec-Jupyter-notebooks/95f98bf9a2b8d7327e72260a8b216148b7242376/pyxspecTutorials/data/spec_sim_bkg.pha --------------------------------------------------------------------------------