ctools 2.1.0.dev
Loading...
Searching...
No Matches
csfindobs.py
Go to the documentation of this file.
1#!/usr/bin/env python
2# ==========================================================================
3# Find observations from an IACT data store
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 sys
22import os
23import json
24import gammalib
25import ctools
26
27
28# =============== #
29# csfindobs class #
30# =============== #
31class csfindobs(ctools.cscript):
32 """
33 Find observations from an IACT data store
34 """
35
36 # Constructor
37 def __init__(self, *argv):
38 """
39 Constructor
40 """
41 # Initialise application by calling the base class constructor
42 self._init_cscript(self.__class__.__name__, ctools.__version__, argv)
43
44 # Set name
45 self._datapath = os.getenv('VHEFITS','')
46 self._prodname = ''
47 self._select_radec = True
48 self._radius = 0.0
49 self._ra = 0.0
50 self._dec = 0.0
51 self._obs_index = ''
52 self._runs = []
53
54 # Return
55 return
56
57
58 # Private methods
59 def _get_parameters(self):
60 """
61 Get parameters from parfile and setup the observation.
62 """
63 # Query datapath. If the parameter is not NONE then use it, otherwise
64 # use the datapath from the VHEFITS environment variable
65 datapath = self['datapath'].string()
66 if gammalib.toupper(datapath) != 'NONE':
67 self._datapath = datapath
68 else:
69 self._datapath = os.getenv('VHEFITS','')
70
71 # Expand environment
72 self._datapath = gammalib.expand_env(self._datapath)
73
74 # Get production name
75 self._prodname = self['prodname'].string()
76
77 # Master index file name
78 master_indx = self['master_indx'].string()
79
80 # Initialise flag if spatial selection is required
81 self._select_radec = True
82
83 # Initialise invalid radius
84 self._radius = 0.0
85
86 # Check for validity of spatial parameters
87 if (self['ra'].is_valid() and
88 self['dec'].is_valid() and
89 self['rad'].is_valid()):
90
91 # Read spatial parameters
92 self._ra = self['ra'].real()
93 self._dec = self['dec'].real()
94 self._radius = self['rad'].real()
95
96 # ... otherwise signal that there are no spatial parameters for
97 # selection
98 else:
99 self._select_radec = False
100
101 # Check Radius for validity
102 if self._radius <= 0.0:
103 self._select_radec = False
104
105 # Query other parameters
106 self['min_qual'].integer()
107 self['expression'].string()
108
109 # Read ahead output parameters
110 if self._read_ahead():
111 self['outfile'].filename()
112
113 # Set filename of JSON master file and raise an exception if the file
114 # does not exist
115 master_file = os.path.join(self._datapath, master_indx)
116 if not os.path.isfile(master_file):
117 msg = ('FITS data store not available. No master index file found '
118 'at "%s". Make sure the file is copied from the server and '
119 'your datapath is set correctly.' % master_file)
120 raise RuntimeError(msg)
121
122 # Open and load JSON master file. If the "dataset" key is not available
123 # then raise an exception
124 json_data = open(master_file).read()
125 data = json.loads(json_data)
126 if not 'datasets' in data:
127 msg = ('Key "datasets" not available in master index file.')
128 raise RuntimeError(msg)
129
130 # Get configurations from JSON master file
131 configs = data['datasets']
132
133 # Initialise obs index file
134 self._obs_index = ''
135
136 # Get name of observation index file
137 for config in configs:
138 if self._prodname == config['name']:
139 self._obs_index = str(os.path.join(self._datapath,
140 config['obsindx']))
141 break
142
143 # If the observation index file name is empty then raise an exception
144 if self._obs_index == '':
145 msg = ('FITS data store "%s" not available. Run csiactdata to get '
146 'a list of available storage names.' % self._prodname)
147 raise RuntimeError(msg)
148
149 # If the observation index file is not a FITS file then raise an
150 # exception
151 filename = gammalib.GFilename(self._obs_index+'[OBS_INDEX]')
152 if not filename.is_fits():
153 msg = ('Observation index file "%s[OBS_INDEX]" for FITS data store '
154 '"%s" not available. Check your master index file or run '
155 'csiactdata to get a list of available storage names.' %
156 (self._obs_index, self._prodname))
157 raise RuntimeError(msg)
158
159 # Write input parameters into logger
160 self._log_parameters(gammalib.TERSE)
161
162 # Return
163 return
164
165
166 # Public methods
167 def process(self):
168 """
169 Process the script
170 """
171 # Get parameters
172 self._get_parameters()
173
174 # Write header into logger
175 self._log_header1(gammalib.TERSE, 'Find observations')
176
177 # Initialise run list
178 self._runs = []
179
180 # Initialise selection expression
181 expr = ''
182
183 # If spatial selection is requested then add an angular separation
184 # expression to the expression string
185 if self._select_radec:
186 expr += 'ANGSEP('+str(self._ra)+','+str(self._dec)+ \
187 ',RA_PNT,DEC_PNT)<='+str(self._radius)
188
189 # Add '&&' connector if expression is not empty
190 if len(expr):
191 expr += '&&'
192
193 # Add always quality expression
194 expr += 'QUALITY<='+str(self['min_qual'].integer())
195
196 # Add user expression is one has been specified
197 expression = self['expression'].string()
198 if (expression != 'NONE' and expression != 'INDEF' and
199 len(expression) > 0):
200 expr += '&&' + expression
201
202 # Write the expression into the logger
203 self._log_value(gammalib.NORMAL, 'Expression', expr)
204
205 # Set filename including the selection expression
206 filename = self._obs_index+'[OBS_INDEX]['+expr+']'
207
208 # Open observation index FITS file
209 fits = gammalib.GFits(filename)
210
211 # If there are entries in the observation index table then append the
212 # observations identifiers to the run list
213 obs_index = fits['OBS_INDEX']
214 if obs_index.nrows() > 0:
215 for i in range(obs_index.nrows()):
216 self._runs.append(obs_index['OBS_ID'][i])
217
218 # Write the number of observations into the logger
219 self._log_value(gammalib.TERSE, 'Observations', len(self._runs))
220
221 # Write the observation identifiers into the logger
222 if len(self._runs) > 0:
223 for i, run in enumerate(self._runs):
224 self._log_value(gammalib.NORMAL, 'Observation %d' % (i+1), run)
225
226 # Close FITS file
227 fits.close()
228
229 # Return
230 return
231
232 def save(self):
233 """
234 Save runlist
235 """
236 # Write header
237 self._log_header1(gammalib.TERSE, 'Save runlist')
238
239 # Get filename
240 outfile = self['outfile'].filename()
241
242 # If the runlist file exists but the clobber flag is not set then signal
243 # that runlist file exists already
244 if outfile.exists() and not self._clobber():
245 msg = ('File "'+outfile+'" exists already, runlist not saved. '
246 'Set clobber=yes to overwrite the file.\n')
247 self._log_string(gammalib.TERSE, msg)
248
249 # ... otherwise save the runlist into a file
250 else:
251
252 # Log file name
253 self._log_value(gammalib.NORMAL, 'Runlist file', outfile.url())
254
255 # Write all runs to file
256 f = open(outfile.url(),'w')
257 for run in self._runs:
258 f.write(str(run)+' \n')
259 f.close()
260
261 # Return
262 return
263
264 def runs(self):
265 """
266 Return run list
267
268 Returns
269 -------
270 runs : list of str
271 A list of runs
272 """
273 # Return
274 return self._runs
275
276
277# ======================== #
278# Main routine entry point #
279# ======================== #
280if __name__ == '__main__':
281
282 # Create instance of application
283 app = csfindobs(sys.argv)
284
285 # Execute application
286 app.execute()