ctools 2.1.0.dev
Loading...
Searching...
No Matches
cstsmapsplit.py
Go to the documentation of this file.
1#!/usr/bin/env python
2# ==========================================================================
3# Create commands to split TS map computation
4#
5# Copyright (C) 2016-2022 Michael Mayer
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20# ==========================================================================
21import os
22import sys
23import math
24import gammalib
25import ctools
26
27
28# ================== #
29# cstsmapsplit class #
30# ================== #
31class cstsmapsplit(ctools.cslikelihood):
32 """
33 Generates commands to split TS map computation
34
35 This class implements the creation of file containing commands to split
36 the computation of a TS map into several machines. It derives from
37 the ctools.cscript class which provides support for parameter files,
38 command line arguments, and logging. In that way the Python script
39 behaves just as a regular ctool.
40 """
41
42 # Consructor
43 def __init__(self, *argv):
44 """
45 Constructor
46 """
47 # Initialise application by calling the appropriate class constructor
48 self._init_cslikelihood(self.__class__.__name__, ctools.__version__, argv)
49
50 # Set data members
51 self._outmap = gammalib.GFilename()
53 self._compute_null = False
54 self._outfile = gammalib.GFilename()
55 self._map = gammalib.GSkyMap()
56 self._cmd = []
57 self._srcname = ''
58
59 # Return
60 return
61
62
63 # Private methods
64 def _get_parameters(self):
65 """
66 Get parameters from parfile and setup the observation
67 """
68 # If there are no observations in container then get some ...
69 if self.obs().size() == 0:
70 self.obs(self._get_observations())
71
72 # Set models if we have none
73 if self.obs().models().size() == 0:
74 self.obs().models(self['inmodel'].filename())
75
76 # Get TS map paramters
77 self._map = self._create_map(self.obs())
78 self._srcname = self['srcname'].string()
79 self._outmap = self['outmap'].filename()
80
81 # Get additional parameters
82 self._bins_per_job = self['bins_per_job'].integer()
83 self._compute_null = self['compute_null'].boolean()
84 self._outfile = self['outfile'].filename()
85
86 # Write input parameters into logger
87 self._log_parameters(gammalib.TERSE)
88
89 # Return
90 return
91
93 """
94 Compute null hypothesis
95
96 Returns
97 -------
98 logl : float
99 Log-likelihood of null hypothesis
100 """
101 # Store original models
102 models_orig = self.obs().models()
103
104 # Get models instance
105 models0 = self.obs().models()
106
107 # Remove test source
108 models0.remove(self._srcname)
109
110 # Set models for null hypothesis
111 self.obs().models(models0)
112
113 # Optimise observation container
114 self.obs().optimize(self.opt())
115
116 # Set original models to container
117 self.obs().models(models_orig)
118
119 # Return optimised log-likelihood of null hypothesis
120 return -(self.opt().value())
121
122
123 # Public methods
124 def process(self):
125 """
126 Process the script
127 """
128 # Get parameters
129 self._get_parameters()
130
131 # Write information into logger
132 self._log_header1(gammalib.TERSE, 'Test source')
133 self._log_string(gammalib.TERSE, str(self.obs().models()[self._srcname]))
134
135 # Set log-likelihood to zero
136 logL0 = 0.0
137
138 # Pre-compute null hypothesis if requested
139 if self._compute_null:
140
141 # Write information into logger
142 self._log_header1(gammalib.TERSE, 'Compute null hypothesis')
143
144 # Compute null hypothesis
145 logL0 = self._compute_null_hypothesis()
146
147 # Write likelihood into logger
148 self._log_value(gammalib.TERSE, 'Source removed', self._srcname)
149 self._log_value(gammalib.TERSE, 'Log-likelihood', repr(logL0))
150
151 # Get parameters of TS map ctool
152 pars = gammalib.GApplicationPars('cttsmap.par')
153
154 # Compute total number of jobs
155 nbins = self._map.npix()
156 njobs = int(math.ceil(float(nbins) / float(self._bins_per_job)) + 0.1)
157
158 # Set parameters to be skipped now, we will deal with them later
159 skip_pars = ['binmin', 'binmax', 'logL0', 'outmap', 'logfile']
160
161 # Set tool name for computation
162 base_command = 'cttsmap'
163
164 # Write information into logger
165 self._log_header1(gammalib.TERSE, 'Create commands')
166 self._log_value(gammalib.TERSE, 'Number of cttsmap calls', njobs)
167
168 # Loop over TS map parameters
169 for par in pars:
170
171 # Skip if we deal with them later
172 if par.name() in skip_pars:
173 continue
174
175 # Skip if parameter was not queried
176 if not self[par.name()].was_queried():
177 continue
178
179 # Set TS map parameter according to input from
180 # this script
181 par.value(self[par.name()].value())
182
183 # Append command to set parameter
184 base_command += ' ' + par.name() + '=' + par.value()
185
186 # Append null hypothesis parameter
187 base_command += ' logL0=' + repr(logL0)
188
189 # Set binning to start from zero
190 binmin = 0
191 binmax = 0
192
193 # Clear command sequence
194 self._cmd = []
195
196 # Loop over jobs and create commands
197 for job in range(njobs):
198
199 # Set specific outmap file name
200 outmap = self._outmap.url().replace('.fits', '_'+str(job)+'.fits')
201
202 # Set bin numbers to be computed in this job
203 binmin = binmax
204 binmax = binmin + self._bins_per_job
205 if binmax > nbins:
206 binmax = nbins
207
208 # Setup sliced command
209 sliced_command = '%s binmin=%s binmax=%s outmap=%s logfile=%s' % \
210 (base_command, str(binmin), str(binmax),
211 outmap, outmap.replace('.fits','.log'))
212
213 # If running in background is requested then append a &
214 if self['run_in_bkg'].boolean():
215 sliced_command += ' &'
216
217 # Append command to list of commands
218 self._cmd.append(sliced_command)
219
220 # Write information into logger
221 if self._logExplicit():
222 self._log('\n')
223 self._log.header2('Commands')
224 for cmd in self._cmd:
225 self._log(cmd)
226 self._log('\n')
227 self._log('\n')
228
229 # Return
230 return
231
232 def save(self):
233 """
234 Save commands to ASCII file
235 """
236 # Get filename
237 filename = self._outfile.url()
238
239 # Open file
240 f = open(filename, 'w')
241
242 # Write commands to file
243 for cmd in self._cmd:
244 f.write(cmd + '\n')
245
246 # Add wait statement
247 f.write('wait\n')
248
249 # Close file
250 f.close()
251
252 # Make file executable
253 os.system('chmod +x %s' % filename)
254
255 # Return
256 return
257
258
259# ======================== #
260# Main routine entry point #
261# ======================== #
262if __name__ == '__main__':
263
264 # Create instance of application
265 app = cstsmapsplit(sys.argv)
266
267 # Execute application
268 app.execute()