Coverage for /wheeldirectory/casa-6.7.0-12-py3.10.el8/lib/py/lib/python3.10/site-packages/casatasks/private/task_imval.py: 83%

220 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-01 07:19 +0000

1import os 

2import numpy 

3 

4from casatools import image, regionmanager, coordsys 

5from casatasks import casalog 

6 

7_ia = image( ) 

8_rg = regionmanager( ) 

9 

10 

11# AUTHOR: S. Jaeger 

12# 

13# NAME: getimaxes 

14# 

15# DESCRIPTION: 

16# This function uses the coordinate information associated 

17# with an image to find where the directional (sky) axes are, 

18# the spectral axes, and the stokes axes. 

19# 

20# INPUT: 

21# imagename string path to a file on disk. 

22# 

23# RETURN 

24# list of four lists, [list1, list2, list3, list4 ], as follows : 

25# list1: ['axis num of 1st sky axis', 'Name of axis' ] 

26# list2: ['axis num of 2nd sky axis', 'Name of axis' ] 

27# list3: ['axis num of spectral axis', 'Spectral' ] 

28# list4: ['axis num of stokes axis', 'Stokes' ] 

29 

30def getimaxes(imagename): 

31 """ 

32 Open an image file, looking at its coordinate system information 

33 to determine which axes are directional, linear, spectral, and 

34 the stokes axies. 

35 

36 The return list or lists contains the axis numbers and names in 

37 the following order: 

38 1. Directional or Linear 

39 2. Directional or Linear 

40 3. Spectral 

41 4. Stokes 

42 

43 Note that if an axis type is not found an empty list is returned 

44 for that axis. 

45 """ 

46 

47 # Get the images coord. sys. 

48 csys=None 

49 _ia.open( imagename ) 

50 csys=_ia.coordsys() 

51 

52 # Find where the directional and channel axies are 

53 # Save the internal placement of the axies in a list 

54 # (which will be in the following order: 

55 # direction1: RA, Longitude, Linear, el, .. 

56 # direction2: DEC, Lattitude, Linear, az, .. 

57 # spectral: 

58 # stokes: I or V 

59 axisTypes=csys.axiscoordinatetypes() 

60 axisNames=csys.names() 

61 

62 # Note that we make a potentially dangerous assumption here 

63 # that the first directional access is always RA, but it 

64 # may not be. The names given to the axies are completely 

65 # arbitrary and can not be used to determine one axis from 

66 # another. 

67 # TODO throw exception??? if we find extra axies or 

68 # unrecognized axies. 

69 retValue=[['',''],['',''],['',''],['','']] 

70 foundFirstDir=False 

71 for i in range( len( axisTypes ) ): 

72 if ( axisTypes[i]=='Direction' or axisTypes[i]=='Linear' ): 

73 if ( not foundFirstDir ) : 

74 retValue[0]=[i,axisNames[i]] 

75 foundFirstDir=True 

76 else: 

77 retValue[1]=[i,axisNames[i]] 

78 elif ( axisTypes[i]=='Spectral' ) : 

79 retValue[2]=[i,axisNames[i]] 

80 elif ( axisTypes[i]=='Stokes' ) : 

81 retValue[3]=[i,axisNames[i]] 

82 

83 if ( csys != None ): 

84 del csys 

85 if ( _ia.isopen() ): 

86 _ia.close() 

87 return retValue 

88 

89 

90# The function that handles the imval task. 

91def imval(imagename, region, box, chans, stokes): 

92 myia = image() 

93 mycsys = coordsys() 

94 try: 

95 # Blank return value. 

96 retValue = { 'blc':[], 'trc':[], 'unit': '', 'data': [], 'mask': []} 

97 casalog.origin('imval') 

98 

99 try: 

100 axes=getimaxes(imagename) 

101 except: 

102 raise RuntimeError("Unable to determine the axes of image: "+imagename) 

103 

104 

105 # Get rid of any white space in the parameters 

106 region = region.replace(' ', '' ) 

107 box = box.replace( ' ', '' ) 

108 chans = chans.replace( ' ', '' ) 

109 stokes = stokes.replace( ' ','' ) 

110 

111 # Default for the chans and stokes parameter is all when the 

112 # aren't given. The easy way is to set them to -1, and let 

113 # the imageregion.py code handle it. 

114 if ( len(chans) < 1 ): 

115 chans='-1' 

116 

117 if ( len(stokes) < 1 ): 

118 stokes='-1' 

119 

120 

121 # If the user hasn't specified any region information then 

122 # find the very last data point -- what ia.getpixelvalue  

123 # defaults too. 

124 

125 if ( len(box)<1 and len(chans)<1 and len(stokes)<1 and len(region)<1 ): 

126 try: 

127 myia.open(imagename) 

128 

129 # Get the default pixelvalue() at the referencepixel pos. 

130 csys=myia.coordsys() 

131 ref_values = csys.referencepixel()['numeric'] 

132 point=[] 

133 for val in ref_values.tolist(): 

134 point.append( int(round(val) ) ) 

135 casalog.post( 'Getting data value at point '+str(point), 'NORMAL' ) 

136 results = myia.pixelvalue(point) 

137 

138 retValue = _imval_process_pixel( results, point ) 

139 retValue['axes']=axes 

140 casalog.post( 'imval task complete for point'+str(point), 'NORMAL1' ) 

141 return retValue 

142 finally: 

143 myia.done() 

144 

145 # If the box parameter only has two value then we copy 

146 # them.  

147 if ( box.count(',') == 1 ): 

148 box = box + ','+ box 

149 

150 # If we are finding the value at a single point this 

151 # is a special case and we use ia.getpixelvalue() 

152 

153 singlePt = _imval_get_single( box, chans, stokes, axes ) 

154 if ( len( singlePt ) == 4 and singlePt.count( -1 ) < 1 ): 

155 try: 

156 casalog.post( 'Getting data value at point '+str(singlePt), 'NORMAL' ) 

157 myia.open( imagename ) 

158 results = myia.pixelvalue( singlePt ) 

159 retValue = _imval_process_pixel( results, singlePt ) 

160 retValue['axes']=axes 

161 casalog.post( 'imval task complete for point '+str(singlePt), 'NORMAL1' ) 

162 return retValue 

163 finally: 

164 myia.done() 

165 

166 

167 # If we've made it here then we are finding the stats 

168 # of a region, which could be a set of single points. 

169 axes=getimaxes(imagename) 

170 statAxes=[] 

171 if ( len(box)>0 ): 

172 statAxes.append(axes[0][0]) 

173 statAxes.append(axes[1][0]) 

174 if ( len(chans)>0 ): 

175 statAxes.append(axes[2][0]) 

176 

177 # If we get to this point and find that nothing was 

178 # given for the box parameter we use the reference 

179 # pixel values. 

180 myia.open(imagename) 

181 mycsys = myia.coordsys() 

182 

183 if ( len(box) == 0 and len(region) == 0): 

184 ctypes = mycsys.axiscoordinatetypes() 

185 ndir = 0 

186 nlin = 0 

187 for ctype in ctypes: 

188 if ctype == 'Direction': 

189 ndir += 1 

190 elif ctype == 'Linear': 

191 nlin += 1 

192 if ndir == 2 or nlin == 2: 

193 try: 

194 ref_values = mycsys.referencepixel()['numeric'] 

195 values = ref_values.tolist() 

196 box = str(int(round(values[axes[0][0]])))+','\ 

197 + str(int(round(values[axes[1][0]])))+',' \ 

198 + str(int(round(values[axes[0][0]])))+','\ 

199 +str(int(round(values[axes[1][0]]))) 

200 except: 

201 raise Exception("Unable to find the size of the input image.") 

202 

203 # Because the help file says -1 is valid, apparently that's supported functionality, good grief 

204 

205 if box.startswith("-1"): 

206 box = "" 

207 if chans.startswith("-1"): 

208 chans = "" 

209 if stokes.startswith("-1"): 

210 stokes = "" 

211 reg = _rg.frombcs( 

212 mycsys.torecord(), myia.shape(), box, chans, 

213 stokes, "a", region 

214 ) 

215 

216 

217 # Now that we know which axes we are using, and have the region 

218 # selected, lets get that stats! NOTE: if you have axes size 

219 # greater then 0 then the maxpos and minpos will not be displayed 

220 if ( 'regions' in reg ): 

221 casalog.post( "Complex region found, only processing the first"\ 

222 " SIMPLE region found", "WARN" ) 

223 reg=reg['regions']['*1'] 

224 retValue = _imval_getregion( imagename, reg ) 

225 retValue['axes']=axes 

226 

227 casalog.post( 'imval task complete for region bound by blc='+str(retValue['blc'])+' and trc='+str(retValue['trc']), 'NORMAL1' ) 

228 return retValue 

229 

230 finally: 

231 myia.done() 

232 mycsys.done() 

233 

234# 

235# Take the results from the ia.pixelvalue() function and 

236# the position given to the function and turn the results 

237# into the desired values; blc, trc, data, and mask 

238# 

239def _imval_process_pixel( results, point ): 

240 retvalue={} 

241 # First check that the results are a dictionary type and that 

242 # it contains the key/value pairs we expect. 

243 if ( not isinstance( results, dict ) ): 

244 casalog.post( "ia.pixelvalue() has returned erroneous data, Python dictionary type expectd.", "WARN" ) 

245 casalog.post( "Value returned is: "+str(results), "SEVERE" ) 

246 return retvalue 

247 

248 if ( 'mask' not in results ): 

249 casalog.post( "ia.pixelvalue() has returned unexpected results, no mask value present.", "SEVERE" ) 

250 return retvalue 

251 

252 if ( 'value' not in results or 'unit' not in results['value'] or 'value' not in results['value'] ): 

253 casalog.post( "ia.pixelvalue() has returned unexpected results, data value absent or ill-formed.", "SEVERE" ) 

254 return retvalue 

255 

256 retValue={ 

257 'blc':point, 'trc': point, 'unit':results['value']['unit'], 

258 'data': numpy.array([results['value']['value']]), 

259 'mask': numpy.array([results['mask']]) 

260 } 

261 return retValue 

262 

263# 

264# Give the box, channel, and stokes values find out 

265# if we are getting the data from a single point in the 

266# image, if so then return that point. 

267def _imval_get_single( box, chans, stokes, axes ): 

268 # If we have more then one point then return an empty list. 

269 try: 

270 junk=int(chans) 

271 junk=int(stokes) 

272 except: 

273 return [] 

274 if ( box.count(';')>0 ): 

275 return [] 

276 

277 # If the channel wasn't specified use the first one only. 

278 if ( len( chans ) < 1 ): 

279 #chans=0 

280 return [] 

281 

282 # If the stokes values weren't specified use the first one only. 

283 if ( len( stokes ) < 1 ): 

284 #stokes=0 

285 return[] 

286 

287 # The two x values and two y values need to be the same if its 

288 # a single point. There may be only two value if its a single 

289 # point too. 

290 x=-1 

291 y=-1 

292 box=box.split(',') 

293 if ( len(box) == 2 ): 

294 x=int(box[0]) 

295 y=int(box[1]) 

296 elif ( len(box) == 4 and box[0]==box[2] and box[1]==box[3]): 

297 x=int(box[0]) 

298 y=int(box[1]) 

299 else: 

300 # We have more then one point, return empty list. 

301 return [] 

302 

303 retvalue=[-1,-1,-1,-1] 

304 

305 retvalue[axes[0][0]]=x 

306 retvalue[axes[1][0]]=y 

307 retvalue[axes[2][0]]=int(chans) 

308 retvalue[axes[3][0]]=int(stokes) 

309 return retvalue 

310 

311# 

312# Use the ia.getregion() function to construct the requested data. 

313def _imval_getregion( imagename, region): 

314 retvalue= {} 

315 myia = image() 

316 try: 

317 # Open the image for processing! 

318 myia.open(imagename) 

319 # Find the array of data and mask values. 

320 data_results=myia.getregion( region=region, dropdeg=True, getmask=False ) 

321 mask_results=myia.getregion( region=region, dropdeg=True, getmask=True ) 

322 

323 # Find the bounding box of the region so we can report it back to 

324 # the user. 

325 bbox = myia.boundingbox( region=region ) 

326 

327 if ( 'blc' not in bbox ): 

328 casalog.post( "ia.boundingbox() has returned unexpected results, blc value absent.", "SEVERE" ) 

329 myia.done() 

330 return retvalue 

331 if ( 'trc' not in bbox ): 

332 casalog.post( "ia.boundingbox() has returned unexpected results, trc value absent.", "SEVERE" ) 

333 myia.done() 

334 return retvalue 

335 

336 # get the pixel coords 

337 mycsys = myia.coordsys() 

338 myarrays = _imval_iterate(bbox['blc'], bbox['trc']) 

339 mycoords = mycsys.toworldmany(myarrays) 

340 outcoords = _imval_redo(data_results.shape, mycoords['numeric']) 

341 

342 avalue = myia.pixelvalue( bbox['blc'].tolist() ) 

343 if ( 'value' not in avalue or 'unit' not in avalue['value'] ): 

344 casalog.post( "ia.pixelvalue() has returned unexpected results, data value absent or ill-formed.", "SEVERE" ) 

345 myia.done() 

346 return retvalue 

347 

348 retvalue={ 

349 'blc':bbox['blc'].tolist(),'trc':bbox['trc'].tolist(), 

350 'unit':avalue['value']['unit'], 'data':data_results, 

351 'mask': mask_results, 'coords': outcoords 

352 } 

353 finally: 

354 myia.done() 

355 return retvalue 

356 

357def _imval_iterate(begins, ends, arrays=None, place=None, depth=0, count=None): 

358 if (depth == 0): 

359 count = [0] 

360 mylist = [] 

361 diff = numpy.array(ends) - numpy.array(begins) + 1 

362 prod = diff.prod() 

363 for i in range(len(begins)): 

364 mylist.append(numpy.zeros([prod])) 

365 arrays = numpy.array(mylist) 

366 for i in range(begins[depth], ends[depth] + 1): 

367 if (depth == 0): 

368 tmpplace = [] 

369 for j in range(len(begins)): 

370 tmpplace.append(0) 

371 place = numpy.array(tmpplace) 

372 place[depth] = i 

373 if (depth == len(begins) - 1): 

374 for k in range(depth + 1): 

375 arrays[k][count[0]] = place[k] 

376 count[0] = count[0] + 1 

377 else: 

378 mydepth = depth + 1 

379 _imval_iterate(begins, ends, arrays, place, mydepth, count) 

380 return arrays 

381 

382def _imval_redo(shape, arrays): 

383 list_of_arrays = [] 

384 for x in range(arrays[0].size): 

385 mylist = [] 

386 for arr in arrays: 

387 mylist.append(arr[x]) 

388 list_of_arrays.append(numpy.array(mylist)) 

389 array_of_arrays = numpy.array(list_of_arrays) 

390 # because shape is an immutable tuple 

391 newshape = list(shape) 

392 newshape.append(array_of_arrays.shape[1]) 

393 return array_of_arrays.reshape(newshape)