;+ ; ; Laboratory for Atmospheric and Space Physics ; University of Colorado, Boulder, Colorado, USA ; ; FILENAME: ; calibration_diagnostics_server.pro ; ; AUTHOR: ; Lon Riesberg ; ; DATE: ; October 15, 2006 ; ; PURPOSE: ; Displays each step of the calibration process in an interactive viewer. ; ; BACKGROUND: ; ; ALGORITHM: ; ; NOTES: ; 1) analyze_cips_calibrations will look for the existence of ; calibration diagnostics files before processing new images. ; If a file already exists, new data won't be processed. ; ; CONSTRAINTS: ; ; OTHER SERVERS/MODULES USED: ; ; RELATED MODULES / CLASSES: ; ; SUPPORTING DATABASE TABLES OR FILES: ; ; USAGE EXAMPLE: ; cal_diagnostics_server = obj_new('calibration_diagnostics_server') ; cal_diagnostics_server->analyze_cips_calibrations, orbit_number ; ; KEYWORD ARGUMENTS: ; ; ---------------------------------------------------------------------- ; CONSTRUCTOR ; ---------------------------------------------------------------------- ; INPUT PARAMETERS: ; ; NOTE: ; ; OUTPUT PARAMETERS: ; NONE ; ; RETURN VALUE: ; A value of 1 is returned if the initialization was successful ; ; KEYWORD ARGUMENTS: ; None ; function calibration_diagnostics_server::init, local_search=local_search ;- if ~keyword_set(local_search) then begin self.local_file_search = 0 ; instantiate any servers needed by this class self.calibrated_px_server = obj_new('calibrated_image_server', self, 'px') self.calibrated_mx_server = obj_new('calibrated_image_server', self, 'mx') self.calibrated_py_server = obj_new('calibrated_image_server', self, 'py') self.calibrated_my_server = obj_new('calibrated_image_server', self, 'my') endif else begin self.local_file_search = 1 endelse return, 1 end ; -------------------------------------------------------------------------- ; Procedure analyze_cips_calibrations ; -------------------------------------------------------------------------- ; PURPOSE: ; ; INPUT PARAMETERS: ; orbit_number - integer value of the AIM mission orbit number ; ; OUTPUT PARAMETERS: ; NONE ; ; RETURN VALUE: ; ; KEYWORD ARGUMENTS: ; orbit_number: ; AIM orbit number ; version_number: ; The version number of Level 1A images to run diagnostics on. If not set, ; will run diagnostics on the data version that's currently being produced. ; Note: if attempting to run diagnostics on a data version that's no longer ; being produced, a previously saved diagnostics file is required. ; save_data: ; Optional flag to indicate whether to save the processed calibration files or not. ; pro calibration_diagnostics_server::analyze_cips_calibrations, orbit_number, version, $ save_data=save_data, prelim=prelim if ~keyword_set(prelim) then prelim=0 viewer_struct = create_struct('image_tlm_timestamp', 0.0d, $ 'raw_image', ptr_new(), $ 'after_spike_corr', ptr_new(), $ 'after_elec_offset_corr', ptr_new(), $ 'after_non_linearity_corr', ptr_new(), $ 'after_conversion_to_dn_rate', ptr_new(), $ 'after_dark_corr', ptr_new(), $ 'after_albedo_calc', ptr_new(), $ 'after_flatfield_corr', ptr_new()) DEVICE, DECOMPOSED=0 LOADCT, 39 ; NOTES: 1. this will continue to retrieve and display diagnostic images until the ; diagnostic viewer returns a '0' or a negative value (indicating an error code) ; 2. saves and/or displays ALL images for each orbit (flat, first light, ; primary science, mapping, last light while orbit_number gt 0 do begin if self.local_file_search eq 0 then begin ; TODO ; If desired, this code will call the level 1A servers directly, making this a ; standalone app and not dependant on normal processing. To set that up, get ; an orbit_info struct for the current orbit_number ; endif else begin orbit_info = create_struct('orbit_number', orbit_number, 'preliminary', prelim) endelse ; ; PX ; px_images = ptr_new() px_viewer_images = ptr_new() px_filename = get_calibration_diagnostics_filename(orbit_info.orbit_number, 'px', version, $ prelim=orbit_info.preliminary) print, px_filename px_images = self->get_px_images(orbit_info, px_filename) if n_elements(px_images) gt 1 then begin ; save data? (useful for standalone mode) if keyword_set(save_data) then begin save, px_images, filename=px_filename endif ; prep images for viewer px_viewer_images = replicate(viewer_struct, n_elements(px_images)) struct_assign, px_images, px_viewer_images fields = tag_names(px_images) for px_idx=0, (n_elements(px_images)-1) do begin for field_idx=1, (n_elements(fields)-1) do begin ; start at 1 since index=0 is a timestamp if size(px_images[px_idx].(field_idx), /type) eq 10 then begin curr_dims = size(*(px_images[px_idx].(field_idx)), /dimensions) curr_cols = curr_dims[0] curr_rows = curr_dims[1] ; reorient if current field is rotated horizontally if curr_cols gt curr_rows then begin *(px_images[px_idx].(field_idx)) = rotate(*(px_images[px_idx].(field_idx)), 4) endif endif endfor endfor endif ; ; MX ; mx_images = ptr_new() mx_viewer_images = ptr_new() mx_filename = get_calibration_diagnostics_filename(orbit_info.orbit_number, 'mx', version, $ prelim=orbit_info.preliminary) mx_images = self->get_mx_images(orbit_info, mx_filename) if n_elements(mx_images) gt 1 then begin ; save data? (useful for standalone mode) if keyword_set(save_data) then begin save, mx_images, filename=mx_filename endif ; prep images for viewer mx_viewer_images = replicate(viewer_struct, n_elements(mx_images)) struct_assign, mx_images, mx_viewer_images fields = tag_names(mx_images) for mx_idx=0, (n_elements(mx_images)-1) do begin for field_idx=1, (n_elements(fields)-1) do begin ; start at 1 since index=0 is a timestamp if size(mx_images[mx_idx].(field_idx), /type) eq 10 then begin curr_dims = size(*(mx_images[mx_idx].(field_idx)), /dimensions) curr_cols = curr_dims[0] curr_rows = curr_dims[1] ; reorient if current field is rotated horizontally if curr_cols gt curr_rows then begin *(mx_images[mx_idx].(field_idx)) = rotate(*(mx_images[mx_idx].(field_idx)), 6) endif endif endfor endfor endif ; ; PY ; py_images = ptr_new() py_viewer_images = ptr_new() py_filename = get_calibration_diagnostics_filename(orbit_info.orbit_number, 'py', version, $ prelim=orbit_info.preliminary) py_images = self->get_py_images(orbit_info, py_filename) if n_elements(py_images) gt 1 then begin ; save data? (useful for standalone mode) if keyword_set(save_data) then begin save, py_images, filename=py_filename endif ; prep images for viewer py_viewer_images = replicate(viewer_struct, n_elements(py_images)) struct_assign, py_images, py_viewer_images fields = tag_names(py_images) for py_idx=0, (n_elements(py_images)-1) do begin for field_idx=1, (n_elements(fields)-1) do begin ; start at 1 since index=0 is a timestamp if size(py_images[py_idx].(field_idx), /type) eq 10 then begin curr_dims = size(*(py_images[py_idx].(field_idx)), /dimensions) curr_cols = curr_dims[0] curr_rows = curr_dims[1] ; reorient if current field is rotated horizontally if curr_cols gt curr_rows then begin *(py_images[py_idx].(field_idx)) = rotate(*(py_images[py_idx].(field_idx)), 7) endif endif endfor endfor endif ; ; MY ; my_images = ptr_new() my_viewer_images = ptr_new() my_filename = get_calibration_diagnostics_filename(orbit_info.orbit_number, 'my', version, $ prelim=orbit_info.preliminary) my_images = self->get_my_images(orbit_info, my_filename) if n_elements(my_images) gt 1 then begin ; save data? (useful for standalone mode) if keyword_set(save_data) then begin save, my_images, filename=my_filename endif ; prep images for viewer my_viewer_images = replicate(viewer_struct, n_elements(my_images)) struct_assign, my_images, my_viewer_images fields = tag_names(my_images) for my_idx=0, (n_elements(my_images)-1) do begin for field_idx=1, (n_elements(fields)-1) do begin ; start at 1 since index=0 is a timestamp if size(my_images[my_idx].(field_idx), /type) eq 10 then begin curr_dims = size(*(my_images[my_idx].(field_idx)), /dimensions) curr_cols = curr_dims[0] curr_rows = curr_dims[1] ; reorient if current field is rotated horizontally if curr_cols gt curr_rows then begin *(my_images[my_idx].(field_idx)) = rotate(*(my_images[my_idx].(field_idx)), 5) endif endif endfor endfor endif ; ; LOAD IMAGES INTO VIEWER ; diagnostic_images = create_struct('px_images', px_viewer_images, $ 'mx_images', mx_viewer_images, $ 'py_images', py_viewer_images, $ 'my_images', my_viewer_images, $ 'orbit_info', orbit_info) ; NOTE: load_calibration_viewer will return a 0 to exit, an orbit number to process, ; or a negative number to indicate an error condition. orbit_number = diagnostic_viewer(diagnostic_images, orbit_number) ; free memory end_memory = memory(/current) str_free, diagnostic_images freed_memory = (end_memory - memory(/current)) / 1E6 if freed_memory gt 5.0 then print, 'memory released: ', freed_memory, ' MB' endwhile return end ; -------------------------------------------------------------------------- ; Function get_px_images ; -------------------------------------------------------------------------- function calibration_diagnostics_server::get_px_images, orbit_info, px_filename print, 'getting px images...' if file_test(px_filename) eq 1 then begin restore, px_filename ; if a diagnostic images file doesn't exist, process the calibrated Level 1A images for this orbit endif else if self.local_file_search ne 1 then begin first_light_images = self.calibrated_px_server->get_data(orbit_info, 'first_light', /diagnostic_mode) primary_science_images = self.calibrated_px_server->get_data(orbit_info, 'primary_science', /diagnostic_mode) last_light_images = self.calibrated_px_server->get_data(orbit_info, 'last_light', /diagnostic_mode) mapping_images = self.calibrated_px_server->get_data(orbit_info, 'mapping', /diagnostic_mode) flatfield_images = self.calibrated_px_server->get_data(orbit_info, 'flat_field', /diagnostic_mode) px_images = self.calibrated_px_server->consolidate_orbit(orbit_info, first_light_images, $ primary_science_images, last_light_images, $ mapping_images, flatfield_images) endif else begin message, px_filename + ' not found', /info return, ptr_new() endelse return, px_images end ; -------------------------------------------------------------------------- ; Function get_mx_images ; -------------------------------------------------------------------------- function calibration_diagnostics_server::get_mx_images, orbit_info, mx_filename print, 'getting mx images...' if file_test(mx_filename) eq 1 then begin restore, mx_filename ; if a diagnostic images file doesn't exist, process the calibrated Level 1A images for this orbit endif else if self.local_file_search ne 1 then begin first_light_images = self.calibrated_mx_server->get_data(orbit_info, 'first_light', /diagnostic_mode) primary_science_images = self.calibrated_mx_server->get_data(orbit_info, 'primary_science', /diagnostic_mode) last_light_images = self.calibrated_mx_server->get_data(orbit_info, 'last_light', /diagnostic_mode) mapping_images = self.calibrated_mx_server->get_data(orbit_info, 'mapping', /diagnostic_mode) flatfield_images = self.calibrated_mx_server->get_data(orbit_info, 'flat_field', /diagnostic_mode) mx_images = self.calibrated_mx_server->consolidate_orbit(orbit_info, first_light_images, $ primary_science_images, last_light_images, $ mapping_images, flatfield_images) endif else begin message, mx_filename + ' not found', /info return, ptr_new() endelse return, mx_images end ; -------------------------------------------------------------------------- ; Function get_py_images ; -------------------------------------------------------------------------- ; PURPOSE: ; ; INPUT PARAMETERS: ; ; OUTPUT PARAMETERS: ; None ; ; KEYWORD ARGUMENTS: ; None ; function calibration_diagnostics_server::get_py_images, orbit_info, py_filename print, 'getting py images...' if file_test(py_filename) eq 1 then begin restore, py_filename ; if a diagnostic images file doesn't exist, process the calibrated Level 1A images for this orbit endif else if self.local_file_search ne 1 then begin first_light_images = self.calibrated_py_server->get_data(orbit_info, 'first_light', /diagnostic_mode) primary_science_images = self.calibrated_py_server->get_data(orbit_info, 'primary_science', /diagnostic_mode) last_light_images = self.calibrated_py_server->get_data(orbit_info, 'last_light', /diagnostic_mode) mapping_images = self.calibrated_py_server->get_data(orbit_info, 'mapping', /diagnostic_mode) flatfield_images = self.calibrated_py_server->get_data(orbit_info, 'flat_field', /diagnostic_mode) py_images = self.calibrated_py_server->consolidate_orbit(orbit_info, first_light_images, $ primary_science_images, last_light_images, $ mapping_images, flatfield_images) endif else begin message, py_filename + ' not found', /info return, ptr_new() endelse return, py_images end ; -------------------------------------------------------------------------- ; Function get_my_images ; -------------------------------------------------------------------------- function calibration_diagnostics_server::get_my_images, orbit_info, my_filename print, 'getting my images...' if file_test(my_filename) eq 1 then begin restore, my_filename ; if a diagnostic images file doesn't exist, process the calibrated Level 1A images for this orbit endif else if self.local_file_search ne 1 then begin first_light_images = self.calibrated_my_server->get_data(orbit_info, 'first_light', /diagnostic_mode) primary_science_images = self.calibrated_my_server->get_data(orbit_info, 'primary_science', /diagnostic_mode) last_light_images = self.calibrated_my_server->get_data(orbit_info, 'last_light', /diagnostic_mode) mapping_images = self.calibrated_my_server->get_data(orbit_info, 'mapping', /diagnostic_mode) flatfield_images = self.calibrated_my_server->get_data(orbit_info, 'flat_field', /diagnostic_mode) my_images = self.calibrated_my_server->consolidate_orbit(orbit_info, first_light_images, $ primary_science_images, last_light_images, $ mapping_images, flatfield_images) endif else begin message, my_filename + ' not found', /info return, ptr_new() endelse return, my_images end ;-------------------------------------------------------------------------- ; CLEANUP ; -------------------------------------------------------------------------- pro calibration_diagnostics_server::cleanup print, "cleaning up calibration_diagnostics_server..." obj_destroy, self.calibrated_px_server obj_destroy, self.calibrated_mx_server obj_destroy, self.calibrated_py_server obj_destroy, self.calibrated_my_server end ; -------------------------------------------------------------------------- ; Object Data Structure Definition ; -------------------------------------------------------------------------- pro calibration_diagnostics_server__define self = {calibration_diagnostics_server, $ local_file_search:0, $ calibrated_px_server:obj_new(), $ calibrated_mx_server:obj_new(), $ calibrated_py_server:obj_new(), $ calibrated_my_server:obj_new()} return end