source: mire/process.py @ 33

Last change on this file since 33 was 33, checked in by meynadie, 12 years ago

filtrage des données couronne

  • Property svn:executable set to *
File size: 13.3 KB
Line 
1#!/bin/env python
2# coding: utf-8
3# Un programme pour exploiter les données des mires
4# -- Frédéric Meynadier
5
6import string
7from numpy import *
8
9from functions import *
10
11from datetime import *
12
13
14from optparse import OptionParser
15parser = OptionParser()
16parser.add_option("-c","--catalog",dest="catalogfile",
17                  help="Name of the catalog file")
18parser.add_option("-r","--reference",dest="reference",
19                  help="Name of the file with reference coordinates")
20parser.add_option("-o","--outputfits",dest="outputfits",
21                  default="output.fits",
22                  help="Name of the output fits file")
23parser.add_option("-m","--measurement",dest="measurement",
24                  default="output.mes",
25                  help="Name of the output measurement file")
26parser.add_option("--ring",dest="ring",
27                  default="output.ring",
28                  help="Name of the output measurement file")
29parser.add_option("-s","--square",dest="square",
30                  default="output.square",
31                  help="Name of the output measurement file")
32parser.add_option("-t","--timing",dest="timing",
33                  help="Name of the input timing file")
34
35
36(options, args) = parser.parse_args ()
37
38# Recherche de la date dans un fichier des timings
39# (généré par recup_date, soit :
40# ls -l $1| awk '{print$8 "\t" $7 "\t" $6}' | sort -k2 | sed -e 's/*//'
41# où $1 est le répertoire contenant les .dat non modifiés.)
42# format attendu : nom_fichier phase_cycle date_isoformat
43
44for line in file(options.timing):
45    line_s = string.split(line)
46    if (len(line_s) > 2):
47        nom = line_s[0] [:-4]
48        if (nom == options.catalogfile[:-6]):
49            dt = datetime.strptime(line_s[2],
50                                   "%Y-%m-%dT%H:%M:%S")
51            phase = float(line_s[1])
52
53# Donner les coordonnées approximatives des 4 repÚres
54
55rep = zeros((4,2))
56i = 0
57for line in open(options.reference):
58    if ((line[0] != "#") and (line != '\n')):
59        spl = string.split(line)
60        rep[i][0] = float(spl[0])
61        rep[i][1] = float(spl[1])
62        i+=1
63
64# Lecture du fichier catalogue
65fields = ["FLUX_MAX",
66          "X_IMAGE",
67          "Y_IMAGE",
68          "THETA_IMAGE",
69          "ELONGATION",
70          "ELLIPTICITY",
71          "FWHM_IMAGE",
72          "ERRX2_IMAGE",
73          "ERRY2_IMAGE"]
74
75catalog = []
76for line in open(options.catalogfile):
77    if ((line[0] != "#") and (line != '\n')):
78        tmp = {}
79        spl = string.split(line)
80        for i in range(len(fields)):
81            tmp[fields[i]] = float(spl[i])
82        tmp['MEAN_DIST_TO_NGBRS']=0
83        catalog.append(tmp)
84
85
86mode_degrade = 0
87# Recherche de la position des repÚres selon catalogue - attention aux doublons
88real_rep = zeros((4,2))
89for i in range(4):
90    detections = 0
91    for source in catalog:
92        pos_source = array([source['X_IMAGE'],source['Y_IMAGE']])
93        max_dist = 5 # pixels
94        if ((modulus(rep[i,:] - pos_source)) < max_dist):
95            max_dist = modulus(rep[i,:] - pos_source)
96            detections +=1
97            real_rep[i,:] = pos_source
98    if (detections > 1):
99        print "Attention ! ambiguïté pour repÚre ",i,\
100              ", nb de détections :",detections
101       
102    if (detections ==0):
103        print "Erreur ! Pas de détection pour repÚre ",i
104        real_rep[i,:]=rep[i,:]
105        mode_degrade = 1
106
107if (mode_degrade==1):
108    print "Passage en mode dégradé, sorties réduites"
109
110# Détermination du centre : barycentre des 4 repÚres
111center = array([sum(real_rep[:,0])/4,sum(real_rep[:,1])/4])
112
113# Vecteurs unitaires de référence
114vec_i = ((real_rep[0,:] - real_rep[1,:])/20 \
115         + (real_rep[3,:] - real_rep[2,:])/20) / 2 
116vec_j = ((real_rep[1,:] - real_rep[2,:])/20 \
117         + (real_rep[0,:] - real_rep[3,:])/20) / 2 
118
119# Détection des noeuds de grille les plus proches de chaque source
120vec_i_2 = dot(vec_i,vec_i)
121vec_j_2 = dot(vec_j,vec_j)
122for source in catalog:
123    pos_source = array([source['X_IMAGE'],source['Y_IMAGE']])-center
124    # dans le référentiel grille (en projetant sur les vecteurs unitaires) :
125    pos_source_grid = array([dot(pos_source,vec_i)/vec_i_2,
126                             dot(pos_source,vec_j)/vec_j_2])
127    # on arrondit au noeud le plus proche
128    knot = pos_source_grid.round()
129    # et on calcule la distance entre les deux
130    r = modulus(pos_source_grid - knot)
131    # enregistrement des résultats
132    source['I_GRID'] = knot[0]
133    source['J_GRID'] = knot[1]
134    source['KNOT_DIST'] = r
135    #if (modulus(knot) <1):
136    #    print source['I_GRID'], source['J_GRID'], source['KNOT_DIST'], pos_source_grid, pos_source,source['X_IMAGE'], source['Y_IMAGE']
137
138# Chasse aux doublons
139# tableau 81*81 contenant :
140# champ 0 : nb de sources rattachée au noeud
141# champ 1 : distance actuelle entre le noeud et la source
142# champ 2 : index courant de la source dans catalog
143# champ 3 : distance moyenne aux voisins (calculé plus tard)
144lookup_sources = zeros((81,81,4))
145for si in range(len(catalog)):
146    source = catalog[si]
147    i = source['I_GRID']+40
148    j = source['J_GRID']+40
149    if ((lookup_sources[i,j,0] < 1)
150        or (lookup_sources[i,j,1] > source['KNOT_DIST'])):
151        lookup_sources[i,j,2] = si
152        lookup_sources[i,j,1] = source['KNOT_DIST']
153    lookup_sources[i,j,0] += 1
154
155# On élimine le noeud (1,1), trop prÚs du "P"
156lookup_sources[41,41,0] = 0
157
158# Calcul de la distance moyenne entre noeuds voisins
159
160fen = 2
161
162shift_list = []
163
164for i in range(-fen,fen+1):
165    for j in range(-fen,fen+1):
166        if (i!=0 or j!=0):
167            shift_list.append([i,j])
168
169for i in range(fen,81-fen):
170    for j in range(fen,81-fen):
171        if (lookup_sources[i,j,0] > 0):
172            knot_idx = int(lookup_sources[i,j,2])
173            catalog[knot_idx]['MEAN_DIST_TO_NGBRS'] = 0
174            nb_voisin = 0
175            distance = 0
176            weights = 0
177            pos_source = array([catalog[knot_idx]['X_IMAGE'],
178                                catalog[knot_idx]['Y_IMAGE']])
179            for shifts in shift_list :
180                i_voisin = i + shifts[0]
181                j_voisin = j + shifts[1]
182                if (lookup_sources[i_voisin,j_voisin,0] > 0):
183                    neigh_idx = int(lookup_sources[i_voisin,j_voisin,2])
184                    nb_voisin +=1
185                    pos_voisin = array([catalog[neigh_idx]['X_IMAGE'],
186                                        catalog[neigh_idx]['Y_IMAGE']])
187                    distance += modulus(pos_source-pos_voisin)
188                    weights += modulus(shifts)
189            if (nb_voisin > 0):
190                catalog[knot_idx]['MEAN_DIST_TO_NGBRS'] = float(distance)/weights
191                lookup_sources[i,j,3] = (float(distance)/weights)
192       
193cleaned_catalog = []
194for i in range(81):
195    for j in range(81):
196        if (lookup_sources[i,j,0] > 0):
197            cleaned_catalog.append(catalog[int(lookup_sources[i,j,2])])
198
199# Sortie du catalogue nettoyé des doublons
200
201of = open('clean.cat','w')
202
203fields = ["FLUX_MAX",
204          "X_IMAGE",
205          "Y_IMAGE",
206          "THETA_IMAGE",
207          "ELONGATION",
208          "ELLIPTICITY",
209          "FWHM_IMAGE",
210          "ERRX2_IMAGE",
211          "ERRY2_IMAGE",
212          "I_GRID",
213          "J_GRID",
214          "KNOT_DIST",
215          "MEAN_DIST_TO_NGBRS"]
216
217fmts = ["%10.3f ",
218        "%8.3f ",
219        "%8.3f ",
220        "%8.3f ",
221        "%8.3f ",
222        "%8.3f ",
223        "%8.3f ",
224        "%8.5f ",
225        "%8.5f ",
226        "%5d ",
227        "%5d ",
228        "%5.3f ",
229        "%8.3f"]
230
231for source in cleaned_catalog:
232    outs = ""
233    for i in range(len(fields)):
234        outs += fmts[i] % source[fields[i]]
235    outs += "\n"
236    of.write(outs)
237
238of.close()
239
240# Génération d'un fichier fits contenant les résultats
241
242
243import pyfits
244
245#a = zeros((2048,2048))
246#
247# patches width in pixel:
248## width = int(modulus(vec_i))
249
250## for i in range(len(cleaned_catalog)):
251##     print i
252##     source = cleaned_catalog[i]
253##     pos_source = array([int(source['X_IMAGE']),int(source['Y_IMAGE'])])
254##     pos_mean_dist = source['MEAN_DIST_TO_NGBRS']
255##     for rel_x in range(-width,width):
256##         for rel_y in range(-width,width):
257##             rel_vec = array([rel_x,rel_y])
258##             # Forme du patch : carré
259##             if ( (dot(rel_vec,vec_i) < vec_i_2/2) and
260##                  (dot(rel_vec,vec_j) < vec_j_2/2)):
261##                 (x,y) = pos_source+rel_vec
262##                 if ( x>0 and x<2048 and y>0 and y<2048):
263##                     a[x,y] = pos_mean_dist
264
265
266
267a = lookup_sources[:,:,3]
268
269for i in range(81):
270    for j in range(81):
271        if (a[i,j] > 0):
272            a[i,j] = 60.0/a[i,j]
273        else :
274            a[i,j] = 1.06
275
276# Interpolation de la case du "P"
277
278a[41,41] = (a[42,41] + a[40,41] + a[41,42] + a[41,40]) /4.
279
280hdu = pyfits.PrimaryHDU(a)
281hdulist = pyfits.HDUList([hdu])
282
283hdu.writeto(options.outputfits,clobber=True)
284
285
286# Facteur d'échelle moyen
287
288tmp = []
289for i in range(81):
290    for j in range(81):
291        if (lookup_sources[i,j,0] == 1):
292            tmp.append(lookup_sources[i,j,3])
293
294
295meas = open(options.measurement,'w')
296
297meas.write("# Moyenne des mesures /  Module vec_i /  Module vec_j / deltaT (min) / date\n")
298# transfo pixels / arcminutes -> mas / pixel
299moyenne_mesures = 60 * (1. / (sum(tmp)/len(tmp)))
300module_veci = 60 * (1. /  modulus(vec_i))
301module_vecj = 60 * (1. /  modulus(vec_j))
302
303outs = "%10.7f %10.7f %10.7f %7.3f %s\n" % (moyenne_mesures,
304                                            module_veci,
305                                            module_vecj,
306                                            phase,
307                                            dt.isoformat())
308meas.write(outs)
309
310meas.close()
311
312## Facteur d'échelle par rapport au centre du champ sur une couronne
313## représentative du diamÚtre solaire
314
315# Quel noeud est (à peu prÚs) au centre ?
316
317
318dist_mini = 2048
319i_centre = 0
320for i in range(len(cleaned_catalog)):
321    source = cleaned_catalog[i]
322    dist = modulus([source["X_IMAGE"] - 1024, source["Y_IMAGE"] - 1024])
323    if (dist < dist_mini):
324        dist_mini = dist
325        i_centre = i
326
327#print "Source au centre : ",cleaned_catalog[i_centre]
328
329# On parcourt une couronne de noeuds et on calcule le facteur d'échelle pour chacun
330
331rmin = 14 # en inter-noeud
332rmax = 18 # en inter-noeud
333
334source_centrale = cleaned_catalog[i_centre]
335
336couronne=[]
337
338for source in cleaned_catalog:
339    tmp = {}
340    dist_knots = modulus([source["I_GRID"] - source_centrale["I_GRID"],
341                          source["J_GRID"] - source_centrale["J_GRID"]])
342    x_rel = source["X_IMAGE"] - source_centrale["X_IMAGE"]
343    y_rel = source["Y_IMAGE"] - source_centrale["Y_IMAGE"]
344    dist_pix = modulus([x_rel,y_rel])
345    if ((dist_knots >= rmin) and (dist_knots <= rmax)):
346        tmp['ScFact'] = dist_knots * 60. / dist_pix # arcsec / pix
347        tmp['r'] = dist_pix
348        tmp['theta'] = math.atan(y_rel/x_rel)
349        if (x_rel < 0):
350            tmp['theta']+=math.pi
351        # Offset de pi pour se mettre en convention "astro"
352        # theta = 0 -> P droit quand nord vers le haut
353        tmp['theta']+=math.pi
354        while (tmp['theta'] < 0):
355            tmp['theta'] += 2*math.pi
356        while (tmp['theta'] >= 2*math.pi):
357            tmp['theta'] -= 2*math.pi
358        # On n'écrit pas les valeurs aberrantes
359        if ((tmp['ScFact'] > 1.05) and (tmp['ScFact'] < 1.07)):
360            couronne.append(tmp)
361
362output_couronne = file(options.ring,'w')
363
364outs = "# phase: %f date: %s\n" % (phase,
365                                 dt.isoformat())
366output_couronne.write(outs)
367
368for source in couronne:
369    outs = "%f %f %10.7f\n" % (source['r'],
370                               math.degrees(source['theta']),
371                               source['ScFact'])
372    output_couronne.write(outs)
373
374
375
376output_couronne.close()
377       
378# On parcourt un carré de surface équivalente à la couronne définie ci dessus
379# Le facteur d'échelle est calculé par rapport au point opposé du carré
380# soit un cÎté de 28 noeuds
381
382
383# Le centre a été trouvé pour la couronne
384i_cen = cleaned_catalog[i_centre]["I_GRID"]
385j_cen = cleaned_catalog[i_centre]["J_GRID"]
386
387# On se refait un "lookup" simplifié
388
389synthese = zeros((81,81,2))
390
391for source in cleaned_catalog:
392    synthese[source['I_GRID'],source['J_GRID'],0] = source['X_IMAGE']
393    synthese[source['I_GRID'],source['J_GRID'],1] = source['Y_IMAGE']
394
395valeurs =  [] 
396for i in range(-14,15):
397    vecteur = synthese[i_cen+14,j_cen+i,:] - synthese[i_cen-14,j_cen+i,:]
398    valeurs.append(modulus(vecteur))
399
400valeurs_orth = []
401for i in range(-14,15):
402    vecteur = synthese[i_cen+i,j_cen+14,:] - synthese[i_cen+i,j_cen-14,:]
403    valeurs_orth.append(modulus(vecteur))
404
405for i in range(len(valeurs)):
406    if valeurs[i] > 0:
407        valeurs[i] = 28*60./valeurs[i]
408
409for i in range(len(valeurs_orth)):
410    if valeurs_orth[i] > 0:
411        valeurs_orth[i] = 28*60./valeurs_orth[i]
412
413
414# on vire les valeurs aberrantes
415def f(x):
416    return ((x < 1.07) and (x > 1.05))
417
418valeurs = filter(f, valeurs)
419valeurs_orth = filter(f, valeurs_orth)
420
421output_square = open(options.square,'w')
422outs = "# moyennes: %f / %f phase: %f date: %s\n" % (mean(valeurs),
423                                                     mean(valeurs_orth),
424                                                     phase,
425                                                     dt.isoformat())
426output_square.write(outs)
427
428for valeur in valeurs:
429    outs = "%f\n" % (valeur)
430    output_square.write(outs)
431
432output_square.write('orth \n')
433
434for valeur in valeurs_orth:
435    outs = "%f\n" % (valeur)
436    output_square.write(outs)
437
438output_square.close()
439
Note: See TracBrowser for help on using the repository browser.