File: flames_cal_ofpos_interact.py

package info (click to toggle)
cpl-plugin-uves 6.1.3+dfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 23,128 kB
  • sloc: ansic: 171,056; sh: 4,359; python: 3,002; makefile: 1,322
file content (342 lines) | stat: -rw-r--r-- 14,274 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
from __future__ import absolute_import
from __future__ import print_function
def log_invocation(fn='/tmp/reflex_invoc.log'):
    """ log invocation of actor for easy reexecution with:
        eval $(cat /tmp/reflex_invoc.log)
    """
    import os, sys
    #if 'REFLEX_DEBUG' not in os.environ:
    #    return
    try:
        with open(fn, 'w') as f:
            path = ""
            s = " ".join(['"%s"' % x for x in sys.argv])
            try:
                import reflex
                path = '"%s:"' % os.path.dirname(reflex.__file__)
            except ImportError:
                pass
            f.write('PYTHONPATH=%s$PYTHONPATH python %s\n' % (path, s)) 
    except:
        pass

# import the needed modules
try:
  import reflex
  import_sucess = True
  import reflex_plot_widgets
  import pipeline_product 
  from pipeline_display import ImageDisplay

#NOTE for developers: 
# -If you want to modify the current script to cope
#  with different parameters, this is the function to modify:
#  setInteractiveParameters()
# -If you want to modify the current script to read different data from
#  the input FITS, this is the function to modify:
#  readFitsData()                  (from class DataPlotterManager) 
# -If you want to modify the current script to modify the plots (using the same
#  data),  this is the function to modify:
#  plotProductsGraphics()          (from class DataPlotterManager)
# -If you want to modify the text that appears in the "Help" button,
#  this is the function to modify:
#  setWindowHelp()
# -If you want to modify the title of the window, modify this function:
#  setWindowTitle()


  #This class deals with the specific details of data reading and final plotting.
  class DataPlotterManager:
    # This function will read all the columns, images and whatever is needed
    # from the products. The variables , self.plot_x, self.plot_y, etc...
    # are used later in function plotProductsGraphics().
    # Add/delete these variables as you need (only that plotProductsGraphics()
    # has to use the same names).
    # You can also create some additional variables (like statistics) after
    # reading the files.
    # If you use a control variable (self.xxx_found), you can modify 
    # later on the layout of the plotting window based on the presence of 
    # given input files. 
    # sof contains all the set of frames
    def readFitsData(self, fitsFiles):
      #Control variable to check if the interesting files where at the input
      self.fibff_all_found = False
      self.slitff_found = False

      #Read all the products
      frames = dict()
      for frame in fitsFiles:
        if frame == '' :
          continue
        category = frame.category
        frames[category] = frame
        #print (frame.name)
      if "FIB_FF_DTC_REDL" in frames and \
         "FIB_FF_DTC_REDU" in frames :  
        self.fibff_all_found = True  

      if "SLIT_FF_DTC_REDL" in frames and \
         "SLIT_FF_DTC_REDU" in frames :  
        self.slitff_found = True  
 
      if self.fibff_all_found == True :
        frame_redl = frames["FIB_FF_DTC_REDL"]
        frame_redu = frames["FIB_FF_DTC_REDU"]

        self.fibreff_redl = pipeline_product.PipelineProduct(frame_redl)
        self.fibreff_redu = pipeline_product.PipelineProduct(frame_redu)
        self.fibreff_next = self.fibreff_redl.all_hdu[0].header['NAXIS3']

      if self.slitff_found == True :
        frame_redl = frames["SLIT_FF_DTC_REDL"]
        frame_redu = frames["SLIT_FF_DTC_REDU"]

        self.slitff_redl = pipeline_product.PipelineProduct(frame_redl)
        self.slitff_redu = pipeline_product.PipelineProduct(frame_redu)

        self.wlen = self.slitff_redl.all_hdu[0].header['ESO INS GRAT2 WLEN']
        self.slitff_redl_next = self.slitff_redl.all_hdu[0].header['NAXIS3']
        self.slitff_redu_next = self.slitff_redu.all_hdu[0].header['NAXIS3']
        self.is_simcal = self.slitff_redl.all_hdu[0].header['ESO OCS SIMCAL']

      self.list_slitff_redl_fid = []
      for i in range(self.slitff_redl_next):
         self.list_slitff_redl_fid.append(i)

      self.list_slitff_redu_fid = []
      for i in range(self.slitff_redu_next):
         self.list_slitff_redu_fid.append(i)

      self.list_fibff_fid = []
      for i in range(self.fibreff_next):
         self.list_fibff_fid.append(i)

      #read first all input image to save time later in case of update 
      self.list_slitff_redl = []
      self.list_slitff_redu = []
      self.list_slitff_redl=self.readAllImages(self.slitff_redl,self.slitff_redl_next)
      self.list_slitff_redu=self.readAllImages(self.slitff_redu,self.slitff_redu_next)

      self.list_fibff_redl = []
      self.list_fibff_redu = []
      self.list_fibff_redl=self.readAllImages(self.fibreff_redl,self.fibreff_next)
      self.list_fibff_redu=self.readAllImages(self.fibreff_redu,self.fibreff_next)


    def plotWidgets(self) :
        widgets = list()

        # Files Selector radiobutton
        labels_fib_ff = self.list_fibff_fid
        labels_slit_ff = self.list_slitff_redl_fid

        self.radiobutton1 = reflex_plot_widgets.InteractiveRadioButtons(self.fibre_flat_selector, self.setFibreSelectCallBack, labels_fib_ff, 0, 
                title="")
        self.radiobutton2 = reflex_plot_widgets.InteractiveRadioButtons(self.slit_flat_selector, self.setSlitSelectCallBack, labels_slit_ff, 0, 
                title="")
        widgets.append(self.radiobutton1)
        widgets.append(self.radiobutton2)

        return widgets

    def setFibreSelectCallBack(self, ext_id) :
        ext_id = int(ext_id)
        self.subplot_allff_redu.cla()
        self.subplot_allff_redl.cla()

        self.displayFibreImages(ext_id)

    def setSlitSelectCallBack(self, ext_id) :
        ext_id = int(ext_id)

        if ext_id < self.slitff_redu_next :
           self.subplot_slitff_redu.cla()
        self.subplot_slitff_redl.cla()

        self.displaySlitImages(ext_id)

    def paragraph(self,text, width=None):
       """ wrap text string into paragraph
           text:  text to format, removes leading space and newlines
           width: if not None, wraps text, not recommended for tooltips as
                  they are wrapped by wxWidgets by default
       """
       import textwrap
       #print 'width=',width,'Text=',text
       if width is None:
           return textwrap.dedent(text).replace('\n', ' ').strip()
       else:
           return textwrap.fill(textwrap.dedent(text), width=width) 

    #Read all images
    def readAllImages(self,obj,next):
        return_list = []
        mylist = list(range(next))
        for i in mylist:
          obj.readImage(fits_extension=0)
          obj.read2DLinearWCS(fits_extension=0)
          return_list.append(obj.image[i])
        return return_list

    #2D image display
    def plotImage(self,obj,subplot,title,tooltip,ext_id):
          #The following commands are done by readAllImages()
          #before calling plotImage in an initial call to save time
          #in case the user ask to update the plots interactively
          #
          #obj.readImage(fits_extension=0)
          #obj.read2DLinearWCS(fits_extension=0)
          #print obj.image[ext_id].shape

          img_obj = ImageDisplay()
          image = obj.image[ext_id]
          y_size, x_size = image.shape

          img_obj.setLabels('X [pix]','Y [pix]')
          img_obj.setXLinearWCSAxis(obj.crval1,obj.cdelt1,obj.crpix1)
          img_obj.setYLinearWCSAxis(obj.crval2,obj.cdelt2,obj.crpix2)

          img_obj.display(subplot, title, self.paragraph(tooltip),image)

    def displayFibreImages(self,fid):
        tooltip=self.setWindowFibreHelp()
        tit_redl=self.setWindowFibreTitle("REDL")
        tit_redu=self.setWindowFibreTitle("REDU")

        self.plotImage(self.fibreff_redu,self.subplot_allff_redu,tit_redu,tooltip,fid)
        self.plotImage(self.fibreff_redl,self.subplot_allff_redl,tit_redl,tooltip,fid)

    def displaySlitImages(self,fid):
        tooltip=self.setWindowSlitHelp()
        tit_redl=self.setWindowSlitTitle("REDL")
        tit_redu=self.setWindowSlitTitle("REDU")
        if fid < self.slitff_redu_next :
           self.plotImage(self.slitff_redu,self.subplot_slitff_redu,tit_redu,tooltip,fid)
        self.plotImage(self.slitff_redl,self.subplot_slitff_redl,tit_redl,tooltip,fid)


    # This function creates all the subplots. It is responsible for the plotting 
    # layouts. 
    # There can different layouts, depending on the availability of data
    # Note that subplot(I,J,K) means the Kth plot in a IxJ grid 
    # Note also that the last one is actually a box with text, no graphs.
    def addSubplots(self, figure):
      if self.fibff_all_found == True:

        ncols=2
        nraws=2
        self.subplot_allff_redu  = figure.add_subplot(nraws,ncols,1)
        self.subplot_slitff_redu = figure.add_subplot(nraws,ncols,2)
        self.subplot_allff_redl  = figure.add_subplot(nraws,ncols,3)
        self.subplot_slitff_redl = figure.add_subplot(nraws,ncols,4)

      else : 
        self.subtext_nodata    = figure.add_subplot(1,1,1)

      self.fibre_flat_selector = figure.add_axes([0.10, 0.46, 0.26, 0.05])
      self.slit_flat_selector = figure.add_axes([0.60, 0.46, 0.26, 0.05])
      tip="Frame Id: (Mouse \n left button)"
      self.fibre_flat_selector.text(0.34, 0.50, tip, color='black', fontsize=10, ha='left', va='center', alpha=1.0)
      self.slit_flat_selector.text(0.34, 0.50, tip, color='black', fontsize=10, ha='left', va='center', alpha=1.0)

    def displayDataNotFound(self):
      #Data not found info
      self.subtext_nodata.set_axis_off()
      self.text_nodata = 'Line prediction not found in the products (PRO.CATG=FIB_FF_DTC_REDL or FIB_FF_DTC_REDU or SLIT_FF_DTC_REDL or SLIT_FF_DTC_REDU)' 
      self.subtext_nodata.text(0.1, 0.6, self.text_nodata, color='#11557c', fontsize=18,
                                 ha='left', va='center', alpha=1.0)
      self.subtext_nodata.tooltip='Images not found in the products'


    # This is the function that makes the plots.
    # Add new plots or delete them using the given scheme.
    # The data has been already stored in self.plot_x, self.plot_xdif, etc ...
    # It is mandatory to add a tooltip variable to each subplot.
    # One might be tempted to merge addSubplots() and plotProductsGraphics().
    # There is a reason not to do it: addSubplots() is called only once at
    # startup, while plotProductsGraphics() is called always there is a resize.
    def plotProductsGraphics(self):
      if self.fibff_all_found == True :
     
         #self.imageTooltips()
         slitff_id=self.list_slitff_redl_fid[0]
         fibreff_id=self.list_fibff_fid[0]
         self.displayFibreImages(fibreff_id)
         self.displaySlitImages(slitff_id)
  

    # This function specifies which are the parameters that should be presented
    # in the window to be edited.
    # Note that the parameter has to be also in the in_sop port (otherwise it 
    # won't appear in the window) 
    # The descriptions are used to show a tooltip. They should match one to one
    # with the parameter list 
    # Note also that parameters have to be prefixed by the 'recipe name:'
    def setInteractiveParameters(self):
      paramList = list()
      paramList.append(reflex.RecipeParameter(recipe='flames_cal_prep_sff_ofpos',displayName='ext_method',group='ofpos',description='Extraction method. <std | opt | fst | fop>'))
      paramList.append(reflex.RecipeParameter(recipe='flames_cal_prep_sff_ofpos',displayName='filter_switch',group='ofpos',description='Filter switch. <none | median>'))
      paramList.append(reflex.RecipeParameter('flames_cal_prep_sff_ofpos',displayName='sat_thr',group='ofpos',description='Saturation threshold'))
      paramList.append(reflex.RecipeParameter(recipe='flames_cal_prep_sff_ofpos',displayName='fileprep',group='ofpos',description='Slitff* and Fibreff* file preparation. If fast extraction method is used it should be set to FALSE.'))
      paramList.append(reflex.RecipeParameter(recipe='flames_cal_prep_sff_ofpos',displayName='save_flat_size',group='ofpos',description='To be sure to use the flat part of a slit flatsone may need to subtract this bit. The default value -1, is used for automatic setting: if WCEN=520 save_flat_size=0, else save_flat_size=2. Values explicitly set by user overwrite this rule. [-1]'))

      return paramList

    def setWindowFibreHelp(self):
      help_text = """
In this window, the user may check the quality of the synthetic fibre
      all-flat which is critical to determine the extraction quality
      of science spectra. The fibres should appear smooth without any
      artefacts. The save_flat_size parameter value may affect quality."""
      return help_text

    def setWindowFibreTitle(self,chip):
      title = 'FLAMES-UVES all fibre flat '+chip
      return title


    def setWindowSlitHelp(self):
      help_text = """
In this window, the user may check the quality of the echelle-slit flats which is critical to determine the extraction quality of science spectra. The images should appear smooth without any artefacts. The save_flat_size parameter value may affect quality."""
      return help_text

    def setWindowSlitTitle(self,chip):
      title = 'FLAMES-UVES slit flat '+chip
      return title

except ImportError:
  import_sucess = 'false'
  print("Error importing modules pyfits, wx, matplotlib, numpy")

#This is the 'main' function
if __name__ == '__main__':
  log_invocation()

  # import reflex modules
  import reflex_interactive_app
  import sys

  # import UVES reflex modules
  import flames_plot_common

  # Create interactive application
  interactive_app = reflex_interactive_app.PipelineInteractiveApp(enable_init_sop=True)

  #Check if import failed or not
  if import_sucess == 'false' :
    interactive_app.setEnableGUI('false')

  #Open the interactive window if enabled
  if interactive_app.isGUIEnabled() :
    #Get the specific functions for this window
    dataPlotManager = DataPlotterManager()
    interactive_app.setPlotManager(dataPlotManager)
    interactive_app.showGUI()
  else :
    interactive_app.passProductsThrough()

  # print outputs
  interactive_app.print_outputs()

  sys.exit()