;------------------------------------------------------------------------- ; ; Automatic file identification, please don't touch or remove : ; ; $Id: festival_data__define.pro 1199 2009-02-24 13:56:17Z esoubrie $ ; ; ------------------------------------------------------------------------ PRO FESTIVAL_DATA::SETPROPERTY, $ FILTERED = filtered, $ PROJECTED_IMAGE = oProjectedImage, $ ENHANCED = enhanced, $orbit_errmsg FITSHEADER = fitsHeader, $ CALIBRATED = calibrated, $ FILTERING_SEQUENCE = filteringSequence, $ PROJCOORD = projCoord, $ MASK_OF_NONMISSING = maskOfNonMissing, $ PROJECTION_MASK = projectionMask, $ PROBE = probe, $ INSTRUMENT = instrument, $ VISU_ELEMENT = oVisuElt IF N_ELEMENTS(filtered) GT 0 THEN BEGIN IF PTR_VALID(self._pFilteredImage) THEN $ *self._pFilteredImage = filtered ELSE $ self._pFilteredImage = PTR_NEW(filtered) END IF N_ELEMENTS(oProjectedImage) GT 0 THEN BEGIN ; Get interpolation method : self._oDataEngine->GETPROPERTY, SELECTION_GUI = oSelectionGUI IF ~OBJ_VALID(oSelectionGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SELECTION_GUI object was found" ; Get system GUI : oSelectionGUI->GETPROPERTY, SYSTEM_OPTIONS_WIZARD = oSystemGUI IF ~OBJ_VALID(oSystemGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SYSTEM_GUI object was found" oSystemGUI->GETPROPERTY, INTERPOLATE = interpolate oProjectedImage->GETPROPERTY, DATA = image, PALETTE = oPalette self._oProjectedImage = OBJ_NEW("IDLGRIMAGE", image, INTERPOLATE = interpolate) IF OBJ_VALID(oPalette) THEN BEGIN oPalette->GETPROPERTY, RED_VALUES = red, GREEN_VALUES = green, BLUE_VALUES = blue copyPalette = OBJ_NEW("IDLGRPALETTE", red, green, blue) self._oProjectedImage->SETPROPERTY, PALETTE = copyPalette END END IF N_ELEMENTS(enhanced) GT 0 THEN BEGIN IF PTR_VALID(self._pEnhancedImage) THEN $ *self._pEnhancedImage = enhanced ELSE $ self._pEnhancedImage = PTR_NEW(enhanced) END IF N_ELEMENTS(fitsHeader) GT 0 THEN BEGIN IF PTR_VALID(self._pFITSHeader) THEN $ *self._pFITSHeader = fitsHeader ELSE $ self._pFITSHeader = PTR_NEW(fitsHeader) END IF N_ELEMENTS(calibrated) GT 0 THEN BEGIN IF PTR_VALID(self._pCalibratedImage) THEN $ *self._pCalibratedImage = calibrated ELSE $ self._pCalibratedImage = PTR_NEW(calibrated) END IF N_ELEMENTS(filteringSequence) GT 0 THEN BEGIN IF PTR_VALID(self._pFilteringSequence) THEN $ *self._pFilteringSequence = filteringSequence ELSE $ self._pFilteringSequence = PTR_NEW(filteringSequence) END IF N_ELEMENTS(projCoord) GT 0 THEN BEGIN IF PTR_VALID(self._pProjCoord) THEN $ *self._pProjCoord = projCoord ELSE $ self._pProjCoord = PTR_NEW(projCoord) END IF N_ELEMENTS(maskOfNonMissing) GT 0 THEN BEGIN IF PTR_VALID(self._pContourOfNonMissing) THEN $ *self._pContourOfNonMissing = maskOfNonMissing ELSE $ self._pContourOfNonMissing = PTR_NEW(maskOfNonMissing) END IF N_ELEMENTS(projectionMask) GT 0 THEN BEGIN IF PTR_VALID(self._pProjectedUserDefinedMaskCoord) THEN $ *self._pProjectedUserDefinedMaskCoord = projectionMask ELSE $ self._pProjectedUserDefinedMaskCoord = PTR_NEW(projectionMask) END IF N_ELEMENTS(probe) GT 0 THEN $ self._probe = probe IF N_ELEMENTS(instrument) GT 0 THEN $ self._instrument = instrument IF N_ELEMENTS(oVisuElt) GT 0 THEN BEGIN IF OBJ_VALID(oVisuElt) THEN BEGIN IF OBJ_ISA(oVisuElt, "FESTIVAL_VISU_ELEMENT") THEN $ self._oVisuElt = oVisuElt END END END PRO FESTIVAL_DATA::GETPROPERTY, $ CALIBRATION_ARRAY = calibrationArray, $ CALIBRATED = pCalibrated, $ FILTERING_SEQUENCE = pFilteringSequence, $ FILTERED = pFiltered, $ ENHANCEMENT = enhancement, $ ENHANCED = pEnhanced, $ PROJCOORD = pProjCoord, $ MASKING = masking, $ UTCDATE = utcDate, $ PROBE = probe, $ INSTRUMENT = instrument, $ IMAGE_COORDINATES = imageCoordinates, $ PROJECTED_IMAGE = oProjectedImage, $ PROJECTION_MASK = pProjectionMask, $ UVRANGE = uvrange, $ DELTAOFIMAGEDIFF = deltaOfImageDiff, $ DISPLAY_ORDER = displayOrder, $ SIZE_OF_DATA = objSize, $ FITSHEADER = pFitsHeader, $ REF_SEARCH_RESULT = oRefSearchResult, $ PALETTE = oPalette, $ UVPERPIXEL_RESOLUTION = uvPerPixelResolution, $ VISU_ELEMENT = oVisuElt, $ SUN_DISTANCE = sun_distance, $ SUNDISTANCE_NORMALIZATION = sundistance_normalization, $ CARRINGTON_LONGITUDE = CarringtonLongitude, $ CARRINGTON_LATITUDE = CarringtonLatitude, $ SOLAR_NORTH_ANGLE = SolarNorthAngle, $ ECLIPTIC_SOLAR_NORTH_ANGLE = EclipticSolarNorthAngle, $ HAEX = haex, $ HAEY = haey, $ HAEZ = haez, $ POLARITY_TYPE = polarityType, $ FILESPECIFICATION = filespec IF ARG_PRESENT(calibrationArray) THEN $ calibrationArray = self._calibrationArray IF ARG_PRESENT(pCalibrated) THEN $ pCalibrated = self._pCalibratedImage IF ARG_PRESENT(pFilteringSequence) THEN $ pFilteringSequence = self._pFilteringSequence IF ARG_PRESENT(pFiltered) THEN $ pFiltered = self._pFilteredImage IF ARG_PRESENT(enhancement) THEN $ enhancement = self._enhancement IF ARG_PRESENT(pEnhanced) THEN $ pEnhanced = self._pEnhancedImage IF ARG_PRESENT(pProjCoord) THEN $ pProjCoord = self._pProjCoord IF ARG_PRESENT(masking) THEN $ masking = self._userMaskParameters IF ARG_PRESENT(utcDate) THEN $ utcDate = self._utcDate IF ARG_PRESENT(probe) THEN $ probe = self._probe IF ARG_PRESENT(instrument) THEN $ instrument = self._instrument IF ARG_PRESENT(imageCoordinates) THEN $ imageCoordinates = self._imageCoordinates IF ARG_PRESENT(oProjectedImage) THEN $ oProjectedImage = self._oProjectedImage IF ARG_PRESENT(pProjectionMask) THEN $ pProjectionMask = self._pProjectedUserDefinedMaskCoord IF ARG_PRESENT(uvRange) THEN $ uvRange = self._UVRange IF ARG_PRESENT(deltaOfImageDiff) THEN $ deltaOfImageDiff = self._deltaOfImageDiff IF ARG_PRESENT(displayOrder) THEN $ displayOrder = self._displayOrder IF ARG_PRESENT(objSize) THEN $ objSize = float(self._sizeInMemory)/1024.0 ;expressed in Ko IF ARG_PRESENT(pFitsHeader) THEN $ pFitsHeader = self._pFITSHeader IF ARG_PRESENT(oRefSearchResult) THEN $ oRefSearchResult = self._oRefSearchResult IF ARG_PRESENT(oPalette) THEN $ IF OBJ_VALID(self._oProjectedImage) THEN $ self._oProjectedImage->GETPROPERTY, PALETTE = oPalette IF ARG_PRESENT(uvPerPixelResolution) THEN $ uvPerPixelResolution = self._UVPerPixelResolution IF ARG_PRESENT(oVisuElt) THEN $ oVisuElt = self._oVisuElt IF ARG_PRESENT(sun_distance) THEN $ sun_distance = self._SunDist IF ARG_PRESENT(sundistance_normalization) THEN $ sundistance_normalization = self._SunDistNormalization IF ARG_PRESENT(CarringtonLongitude) THEN $ CarringtonLongitude = self._CarringtonLongitude IF ARG_PRESENT(CarringtonLatitude) THEN $ CarringtonLatitude = self._CarringtonLatitude IF ARG_PRESENT(SolarNorthAngle) THEN $ SolarNorthAngle = self._SolarNorthAngle IF ARG_PRESENT(EclipticSolarNorthAngle) THEN $ EclipticSolarNorthAngle = self._EclipticSolarNorthAngle IF ARG_PRESENT(HAEX) THEN $ haex = self._HAEX IF ARG_PRESENT(HAEY) THEN $ haey = self._HAEY IF ARG_PRESENT(HAEZ) THEN $ haez = self._HAEZ IF ARG_PRESENT(polarityType) THEN $ polarityType = self._polarityType IF ARG_PRESENT(filespec) THEN $ filespec = self._fileSpecification END ;+ ; NAME: ; FESTIVAL_DATA::GETMISSINGMASK ; ; PURPOSE: ; Returns a pointer to a byte of "good" values. ; ; INPUTS: ; None ; ; KEYWORD PARAMETERS: ; ; None ; ; OUTPUTS: ; ; A pointer to a byte array of "good" projected images values. ; ; MODIFICATION HISTORY: ; 31/08/06 - IAS ORSAY ;- FUNCTION FESTIVAL_DATA::GETMISSINGMASK RETURN, self._pContourOfNonMissing END ;+ ; NAME: ; FESTIVAL_DATA::BUILD_PROJ_MASK ; ; PURPOSE: ; ; Defines the _pProjectedUserDefinedMaskCoord property that will be ; used to set the position of the data and its mask. ; If a user mask is defined, its projection is computed. ; Otherwise, the mask is computed using the "good/missing" contour ; computed in the CREATE_PROJECTED_IMAGE procedure. ; ; INPUTS: ; oMaskingGUI ; ; KEYWORD PARAMETERS: ; ; None ; ; OUTPUTS: ; ; ; ; MODIFICATION HISTORY: ; 31/08/06 - IAS ORSAY ; 23/01/07 - IAS ORSAY Correction of the case where the contour is ; build using the "missing/good value" mask. ; New UVRange definition is also taken into account ;- FUNCTION FESTIVAL_DATA::BUILD_PROJ_MASK, oMaskingGUI, oProjcoordGUI ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL ; Free memory : IF PTR_VALID(self._pProjectedUserDefinedMaskCoord) THEN $ PTR_FREE, self._pProjectedUserDefinedMaskCoord ; Reset object properties : self._userMaskParameters = {FESTIVAL_MASKING} RETURN, !FALSE END IF ~OBJ_VALID(oMaskingGUI) THEN $ MESSAGE, "An invalid FESTIVAL_MASKING_GUI object was passed" IF ~OBJ_ISA(oMaskingGUI, "FESTIVAL_MASKING_GUI") THEN $ MESSAGE, "An invalid FESTIVAL_MASKING_GUI object was passed" ; Test _oProjectedImage : IF ~OBJ_VALID(self._oProjectedImage) THEN $ MESSAGE, "No valid _oProjectImage buffer available" IF ~PTR_VALID(self._pProjCoord) THEN $ MESSAGE, "No valid _pProjCoord structure available" ; Get projCoordGUI object properties : oProjcoordGUI->GETPROPERTY, ALL = all ; Get target projCoord structure : projCoordStruct = all[self._probe] ; Get oMaskingGUI properties : oMaskingGUI->GETPROPERTY, ALL = all ; Get target masking structure : maskingStruct = all[self._probe, self._instrument] projectionON = projCoordStruct._instrument[self._instrument] IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> BUILD_PROJ_MASK" ; Check if masking is required : IF maskingStruct._maskingON THEN BEGIN ; Get image coordinates : lon1 = self._imageCoordinates[0] lat1 = self._imageCoordinates[1] lon2 = self._imageCoordinates[2] lat2 = self._imageCoordinates[3] ; Get normalised coordinates of the center and radii of the mask : xCenter = maskingStruct._imageXCenter yCenter = maskingStruct._imageYCenter percentRadii = maskingStruct._radii IF !DEBUG EQ !TRUE THEN BEGIN PRINT, "MASKING PARAMETERS : " PRINT, "xCenter = ", xCenter PRINT, "yCenter = ", yCenter PRINT, "radii = ", percentRadii END r = ((lon2-lon1) < (lat2-lat1))*percentRadii / 2.0 ; Compute (longitude/latitude) mask : angles = (1/!DRADEG)*INDGEN(360) lon = lon1 > (lon1 + xCenter*(lon2-lon1) + r*COS(angles)) < lon2 lat = lat1 > (lat1 + yCenter*(lat2-lat1) + r*SIN(angles)) < lat2 IF !DEBUG EQ !TRUE THEN BEGIN PRINT, "LONGITUDE : ", MIN(lon), MAX(lon) PRINT, "LATITUDE : ", MIN(lat), MAX(lat) END IF (projectionON EQ !TRUE) THEN BEGIN ; Change it to UV coordinates : ; lat/lon to UV conversion : IF !DEBUG EQ !TRUE THEN $ PRINT, "--------------------------------> MASK IS PROJECTED" UVProj = MAP_PROJ_FORWARD(lon, lat, MAP_STRUCTURE = (*self._pProjCoord)._sMap) ENDIF ELSE BEGIN ; in this case, lon,lat just needs to ; be interpolated but not really ; projected because image has not been ; projected U_min = self._UVRange[0,0] V_min = self._UVRange[1,0] U_max = self._UVRange[0,2] V_max = self._UVRange[1,2] IF !DEBUG EQ !TRUE THEN $ PRINT, "--------------------------------> MASK IS INTERPOLATED" U_lon = ( ( lon - lon1 ) / ( lon2 - lon1 ) )*( U_max - U_min ) + U_min V_lat = ( ( lat - lat1 ) / ( lat2 - lat1 ) )*( V_max - V_min ) + V_min UVProj= transpose([[U_lon],[V_lat]]) ENDELSE ; Use mask of "good" values to build _pProjectedUserDefinedMaskCoord : END ELSE BEGIN ; in this case, the UV coordinates of ; the mask have already been computed : IF ~PTR_VALID(self._pContourOfNonMissing) THEN $ MESSAGE, "Mask of non missing values is not available" UVProj = *self._pContourOfNonMissing IF !DEBUG EQ !TRUE THEN $ PRINT, "------------------------------> MASK IS BUILD USING NON MISSING DATA AFTER PROJECTION" END ; Store mask contour values into _pProjectedUserDefinedMaskCoord buffer : IF N_ELEMENTS(UVProj) EQ 0 THEN $ MESSAGE, "Projection mask could not be computed" ; Always set _userMaskParameters property : self._userMaskParameters = maskingStruct IF PTR_VALID(self._pProjectedUserDefinedMaskCoord) THEN $ *self._pProjectedUserDefinedMaskCoord = TEMPORARY(UVProj) ELSE $ self._pProjectedUserDefinedMaskCoord = PTR_NEW(UVProj, /NO_COPY) RETURN, !TRUE END ;+ ; NAME: ; FESTIVAL_DATA::CREATE_PROJECTED_IMAGE ; ; PURPOSE: ; Create the projected image from the user settings. ; ; INPUTS: ; ; oProjcoordGUI : object reference to a FESTIVAL_PROJCOORD_GUI object. ; ; oColourGUI : object reference to a FESTIVAL_COLOUR_GUI object. ; ; KEYWORD PARAMETERS: ; ; NO_PROJECTION_NEEDED : set this keyword to a non-null value to indicate that no projection should be computed. ; ; OUTPUTS: ; ; !TRUE if projection was computed OK, !FALSE otherwise. ; ; Properties affected by this method : ; ; - self._UVRange : if image is projected, it is set to the ; projected matrice coordinates (given by MAP_PROJ_IMAGE), otherwise, ; it is set to the projection of the corners of the data ; ; - self._oProjectedImage : the projected image or the ; enhanced image if no projection is performed ; ; - self._pContourOfNonMissing : (variable contourXY in the ; code) : set to the contour of the missing/good values if ; projection has been performed, set to : ; [[self._UVRange], [self._UVRange[*, 0]]] otherwise. ; ; - self._UVPerPixelResolution ; ; - self._pProjCoord ; ; ; MODIFICATION HISTORY: ; 31/08/06 - IAS ORSAY ; 23/01/07 - IAS ORSAY UVRange definition with 4 points instead of 2 ; and _pContourOfNonMissing is always in UV ; space. ; ;- FUNCTION FESTIVAL_DATA::CREATE_PROJECTED_IMAGE, oProjcoordGUI, oColourGUI, $ MISSING = missing, $ NO_PROJECTION_NEEDED = No_Projection_Needed ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL ; Free memory : IF OBJ_VALID(self._oProjectedImage) THEN $ OBJ_DESTROY, self._oProjectedImage IF PTR_VALID(self._pContourOfNonMissing) THEN $ PTR_FREE, self._pContourOfNonMissing IF PTR_VALID(self._pProjCoord) THEN $ PTR_FREE, self._pProjCoord RETURN, !FALSE END ; Get interpolation method : self._oDataEngine->GETPROPERTY, SELECTION_GUI = oSelectionGUI IF ~OBJ_VALID(oSelectionGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SELECTION_GUI object was found" ; Get system GUI : oSelectionGUI->GETPROPERTY, SYSTEM_OPTIONS_WIZARD = oSystemGUI IF ~OBJ_VALID(oSystemGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SYSTEM_GUI object was found" oSystemGUI->GETPROPERTY, INTERPOLATE = interpolate ; Check for input objects validity : IF ~OBJ_VALID(oProjcoordGUI) THEN $ MESSAGE, "An invalid FESTIVAL_PROJCOORD_GUI object was passed" IF ~OBJ_ISA(oProjcoordGUI, "FESTIVAL_PROJCOORD_GUI") THEN $ MESSAGE, "An invalid FESTIVAL_PROJCOORD_GUI object was passed" IF ~OBJ_VALID(oColourGUI) THEN $ MESSAGE, "An invalid FESTIVAL_COLOUR_GUI object was passed" IF ~OBJ_ISA(oColourGUI, "FESTIVAL_COLOUR_GUI") THEN $ MESSAGE, "An invalid FESTIVAL_COLOUR_GUI object was passed" ; Need an enhanced image to be projected : IF ~PTR_VALID(self._pEnhancedImage) THEN $ MESSAGE, "No enhanced image available" ; Check keywords : IF N_ELEMENTS(No_Projection_Needed) EQ 0 THEN $ No_Projection_Needed = !FALSE ; Get projCoordGUI object properties : oProjcoordGUI->GETPROPERTY, ALL = all ; Get target projCoord structure : projCoordStruct = all[self._probe] ; Default value for uvrange : ; remember that ; imageCoordinates = [ lon1, lat1, lon2, lat2 ] ; and that UVRange is defined like that : ; ; C0 = UVRange(*,0) = lower left corner ; C1 = UVRange(*,1) = lower right corner ; C2 = UVRange(*,2) = upper right corner ; C3 = UVRange(*,3) = upper right corner ; ; C3 ---- C2 ; | | ; | | ; C0 ---- C1 ; These default values will be used if ; no projection of the image is done : ; before projection, saturate latitude in [-89.95, 89.95] self._imageCoordinates[1] = self._imageCoordinates[1] > (-89.5) self._imageCoordinates[3] = self._imageCoordinates[3] < 89.5 self._UVRange = MAP_PROJ_FORWARD(self._imageCoordinates[[0, 2, 2, 0]], $ self._imageCoordinates[[1, 1, 3, 3]], $ MAP = projCoordStruct._sMap) ; THE FOLLOWING 'RECTANGULARISATION' MAY BE CHANGED IN THE FUTURE ; BUT NORMALISATION WOULD HAVE TO BE REDEFINED : ; we computed the 'equivalent' rectangle image ; Rectangle position is correctly centered C0 = self._UVRange[*,0] C1 = self._UVRange[*,1] C2 = self._UVRange[*,2] C3 = self._UVRange[*,3] u_min = (C0[0]+C3[0])/2.0 u_max = (C1[0]+C2[0])/2.0 v_min = (C0[1]+C1[1])/2.0 v_max = (C2[1]+C3[1])/2.0 self._UVRange = [[u_min,v_min],[u_max,v_min],[u_max,v_max],[u_min,v_max]] ; END OF 'RECTANGULARISATION' ; Default contour of "good" values : contourXY = [[self._UVRange], [self._UVRange[*, 0]]] ; Case where projection has not been prohibited : IF ((No_Projection_Needed EQ !FALSE) AND (all[self._probe]._smap.up_name NE 'Equirectangular')) THEN BEGIN projectionON = projCoordStruct._instrument[self._instrument] ; Need to project : IF (projectionON EQ !TRUE) THEN BEGIN IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> IMAGE IS PROJECTED" projectedBuffer = MAP_PROJ_IMAGE($ ; IN : *self._pEnhancedImage, $ self._imageCoordinates, $ MAP_STRUCTURE = projCoordStruct._sMap, $ ; OUT : UVRANGE = uvrangeImage, $ MASK = mask, $ /BILINEAR) ; uvrangeImage contains the range of the UV coordinates of the Result ; in a four-element array of the form [U min, V min, U max, V max] ; We're not interested by the mask, but by its contours : ; Find boundaries : indices = WHERE(mask GT 0, count, NCOMPLEMENT = nComp) IF ~count THEN $ MESSAGE, "Mask of non missing values is incorrect" ; If some values are missing, build new contour IF (nComp NE 0) THEN BEGIN info = SIZE(mask) nCols = info[1] nRows = info[2] ; Call FIND_BOUNDARY : contourXY = FIND_BOUNDARY(indices, XSIZE = nCols, YSIZE = nRows) contourXY = [[contourXY], [contourXY[*, 0]]] ; now contourXY needs to be translated in UV coordinates : ; Get projected matrice coordinates : u1 = uvrangeImage[0] v1 = uvrangeImage[1] u2 = uvrangeImage[2] v2 = uvrangeImage[3] ; Find XMin, XMax : xMin = MIN(contourXY[0, *], MAX = xMax) xFac = (u2-u1) / (xMax-xMin) ; Find YMin, YMax : yMin = MIN(contourXY[1, *], MAX = yMax) yFac = (v2-v1) / (yMax-yMin) ; Change it to longitude, latitude : u_tab = REFORM(contourXY[0, *] * xFac + u1) v_tab = REFORM(contourXY[1, *] * yFac + v1) contourXY = TRANSPOSE([[u_tab], [v_tab]]) END ELSE BEGIN ; the projection did not produce any missing value contourXY = [ [uvrangeImage[[0, 1]]],$ [uvrangeImage[[2, 1]]],$ [uvrangeImage[[2, 3]]],$ [uvrangeImage[[0, 3]]],$ [uvrangeImage[[0, 1]]] ] ENDELSE ; End if test to know if values are missing or not ; now that projection is done, ; store the coordinates of the projected matrice ; which is not equivalent to the UV coordinates ; of the initial image corners (the projection ; of the corners may not be a rectangle, this result is ; by construction a rectangle) self._UVRange = [ [uvrangeImage[[0, 1]]],$ [uvrangeImage[[2, 1]]],$ [uvrangeImage[[2, 3]]],$ [uvrangeImage[[0, 3]]] ] ; This property will be used to normalize the texture_coord ; attribute of the visu_element, i.e. to normalize the ; user mask END ELSE BEGIN ; END OF CASE (projectionON EQ !TRUE) ; case where the user chose the projection OFF projectedBuffer = *self._pEnhancedImage IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> IMAGE IS NOT PROJECTED" ENDELSE END ELSE BEGIN ; END OF CASE ((~No_Projection_Needed) EQ !TRUE) projectedBuffer = *self._pEnhancedImage IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> IMAGE IS NOT PROJECTED" ENDELSE ; Build an IDLGRIMAGE object out of projectedBuffer : IF N_ELEMENTS(projectedBuffer) EQ 0 THEN $ MESSAGE, "The projected image could not be computed" self._oRefSearchResult->GETPROPERTY, F_FILTER = filter, F_WAVE = wave deltaOfImageDiff = self._deltaOfImageDiff NE 0 ; Check waves array : IF PTR_VALID(!WAVES_ARRAY[self._probe, self._instrument]) THEN BEGIN ; Get the waves : waves = *!WAVES_ARRAY[self._probe, self._instrument] ; Is there an 'All' string ? IF waves[N_ELEMENTS(waves)-1] EQ 'All' THEN BEGIN ; 'All' is at the first position : IF waves[0] EQ 'All' THEN $ vecWave = 0 ELSE BEGIN ; Remove extra 'All' string : waves = waves[0:(N_ELEMENTS(waves)-2)] ; Find target wave : vecWave = WHERE(STRUPCASE(waves) EQ STRUPCASE(wave)) > 0 END ; No 'All' at the end : END ELSE $ ; If no wave is found, uses vecWave = 0. vecWave = WHERE(waves EQ wave) > 0 END ELSE $ MESSAGE, "The !WAVES_ARRAY array does not contain valid information" IF PTR_VALID(!FILTERS_ARRAY[self._probe, self._instrument]) THEN BEGIN ; Get the filters : filters = *!FILTERS_ARRAY[self._probe, self._instrument] ; Perform comparison : if no filter is found, uses vecFilter = 0 vecFilter = WHERE(STRUPCASE(filters) EQ STRUPCASE(filter), countFilter) > 0 END ELSE $ MESSAGE, "The !FILTERS_ARRAY array does not contain valid information" ; Build the default palette if necessary : oColourGUI->GETPROPERTY, ALL = allPalettes IF ~OBJ_VALID(allPalettes[self._probe, self._instrument, $ vecFilter[0], vecWave[0], deltaOfImageDiff]) THEN $ oColourGUI->CREATE_PALETTE, self._probe, self._instrument, $ vecFilter[0], vecWave[0], deltaOfImageDiff oColourGUI->GETPROPERTY, ALL = allPalettes ; Update object properties : IF OBJ_VALID(self._oProjectedImage) THEN $ self._oProjectedImage->SETPROPERTY, DATA = TEMPORARY(projectedBuffer), $ PALETTE = allPalettes[self._probe, self._instrument, vecFilter[0], vecWave[0], deltaOfImageDiff] ELSE $ self._oProjectedImage = OBJ_NEW("IDLGRIMAGE", TEMPORARY(projectedBuffer), $ PALETTE = allPalettes[self._probe, self._instrument, vecFilter[0], vecWave[0], deltaOfImageDiff], $ INTERPOLATE = interpolate) ;WARNING : MAYBE TO BE CHANGED TO BE COMPLETELY CORRECT. self._oProjectedImage->GETPROPERTY, DIMENSIONS = dims self._UVPerPixelResolution = (self._uvRange[*,2]-self._uvRange[*,0])/DOUBLE(dims) ; Store byte array of "good" values in a pointer : IF PTR_VALID(self._pContourOfNonMissing) THEN $ *self._pContourOfNonMissing = contourXY ELSE $ self._pContourOfNonMissing = PTR_NEW(contourXY, /NO_COPY) ; Store projection/coordinates structure : IF PTR_VALID(self._pProjCoord) THEN $ *self._pProjCoord = TEMPORARY(projCoordStruct) ELSE $ self._pProjCoord = PTR_NEW(projCoordStruct, /NO_COPY) IF (No_Projection_Needed EQ !TRUE) THEN BEGIN ; if data is just computed in order to build a difference, ; record the information. ; Otherwise, COMPUTE_DATA_SIMILARITY would think it has been projected (*self._pProjCoord)._instrument[self._instrument]=!FALSE ENDIF ; Update size in memory : self->UPDATESIZEINMEMORY RETURN, !TRUE END ;+ ; NAME: ; FESTIVAL_DATA::MAKE_DIFF ; ; PURPOSE: ; Compute the difference between two FESTIVAL_DATA objects. ; ; INPUTS: ; ; oFestivalData1 : first FESTIVAL_DATA object. ; ; oFestivalData2 : second FESTIVAL_DATA object. Difference is computed by oFestivalData2-oFestivalData1. ; ; oFestivalFilterGUI : a reference to a FESTIVAL_FILTER_GUI object. ; ; oFestivalCalibrationGUI : a reference to a FESTIVAL_CALIBRATION_GUI object. ; ; oFestivalProjCoordGUI : a reference to a FESTIVAL_PROJCOORD_GUI object. ; ; KEYWORD PARAMETERS: ; None ; ; OUTPUTS: ; A FESTIVAL_DATA difference object. ; ; MODIFICATION HISTORY: ; 31/08/06 - IAS ORSAY ;- FUNCTION FESTIVAL_DATA::MAKE_DIFF, oFestivalData1, oFestivalData2, $ oFestivalFilterGUI, $ oFestivalCalibrationGUI, $ oFestivalProjCoordGUI ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL RETURN, !FALSE END IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> MAKE_DIFF" ; Check probe/instrument values : oFestivalData1->GETPROPERTY, PROBE = probe1, INSTRUMENT = instrument1, $ FILTERING_SEQUENCE = pFilteringSequence1, CALIBRATION_ARRAY = calibrationArray1, $ PROJCOORD = pProjCoord1, FILTERED = pFiltered1, UTCDATE = utcDate1, $ POLARITY_TYPE = polarityType1 oFestivalData2->GETPROPERTY, PROBE = probe2, INSTRUMENT = instrument2, $ FILTERING_SEQUENCE = pFilteringSequence2, CALIBRATION_ARRAY = calibrationArray2, $ PROJCOORD = pProjCoord2, FILTERED = pFiltered2, UTCDATE = utcDate2, $ POLARITY_TYPE = polarityType2 ; These errors are directly thrown by the catch : IF probe1 NE probe2 OR instrument1 NE instrument2 THEN $ MESSAGE, "Incompatible probe/instrument FESTIVAL_DATA objects" IF ~PTR_VALID(pFiltered1) OR ~PTR_VALID(pFiltered2) THEN $ MESSAGE, "Cannot compute object difference as one or both _pFilteredImages buffers are empty" ; ; ********************************************************************************** ; ; ; Check oFestival1, oFestival2, oFestivalFilterGUI compatibility : ; oFestivalFilterGUI->GETPROPERTY, ALL = all ; ; ; Get the target property : ; targetProp = all[probe1, instrument1] ; ; array0 = '' ; IF PTR_VALID(targetProp._pFilteringSequence) THEN $ ; array0 = STRCOMPRESS(STRUPCASE(*targetProp._pFilteringSequence), /REMOVE_ALL) ; array1 = '' ; IF PTR_VALID(pFilteringSequence1) THEN $ ; array1 = STRCOMPRESS(STRUPCASE(*pFilteringSequence1), /REMOVE_ALL) ; array2 = '' ; IF PTR_VALID(pFilteringSequence2) THEN $ ; array2 = STRCOMPRESS(STRUPCASE(*pFilteringSequence2), /REMOVE_ALL) ; ; ; Check for array equality : ; IF ~(ARRAY_EQUAL(array0, array1) AND ARRAY_EQUAL(array1, array2)) THEN $ ; MESSAGE, "Incompatible FESTIVAL_FILTER_GUI/FESTIVAL_DATA objects" ; ********************************************************************************** ; Check oFestival1, oFestival2, oFestivalCalibrationGUI compatibility : oFestivalCalibrationGUI->GETPROPERTY, ALL = all ; Get the target property : targetProp = all[probe1, instrument1] ; Check for calibration models equality : IF ~(TESTSTRUCTEQUALITY(targetProp, calibrationArray1) AND TESTSTRUCTEQUALITY(calibrationArray1, calibrationArray2)) THEN $ MESSAGE, "Incompatible FESTIVAL_CALIBRATION_GUI/FESTIVAL_DATA objects" ; ********************************************************************************** ; Check oFestivalData1, oFestivalData2, oFestivalProjCoordGUI compatibility : oFestivalProjCoordGUI->GETPROPERTY, ALL = all ; Get the target property : targetProp = all[probe1] IF ~(targetProp._coordSystem EQ (*pProjCoord1)._coordSystem AND $ targetProp._coordSystem EQ (*pProjCoord2)._coordSystem) THEN $ MESSAGE, "Incompatible coordinate systems" ; Copy objects by assignment : STRUCT_ASSIGN, oFestivalData2, self ; Remove unwanted items : : ; Reset _oProjectedImage property : self._oProjectedImage = OBJ_NEW() ; Reset _pEnhancedImage property : self._pEnhancedImage = PTR_NEW() ; Reset _pFITSHeader property : self._pFITSHeader = PTR_NEW() oFestivalData2->GETPROPERTY, FITSHEADER = pFitsHeader IF PTR_VALID(pFitsHeader) THEN $ self._pFITSHeader = PTR_NEW(*pFitsHeader) ; Reset _pCalibratedImage property : self._pCalibratedImage = PTR_NEW() ; Reset _pFilteringSequence : self._pFilteringSequence = PTR_NEW() oFestivalData2->GETPROPERTY, FILTERING_SEQUENCE = pFilteringSequence IF PTR_VALID(pFilteringSequence) THEN $ self._pFilteringSequence = PTR_NEW(*pFilteringSequence) ; Reset _pProjCoord : self._pProjCoord = PTR_NEW() oFestivalData2->GETPROPERTY, PROJCOORD = pProjCoord IF PTR_VALID(pProjCoord) THEN $ self._pProjCoord = PTR_NEW(*pProjCoord) ; Reset _pContourOfNonMissing : self._pContourOfNonMissing = PTR_NEW() ; Reset _pProjectedUserDefinedMaskCoord : self._pProjectedUserDefinedMaskCoord = PTR_NEW() ; Compute _pFilteredImage : self._pFilteredImage = PTR_NEW(*pFiltered2 - *pFiltered1) ; Set _UTCDate property : self._UTCDate = utcDate2 ; Set _deltaOfImageDiff property : self._deltaOfImageDiff = utcDate2-utcDate1 oFestivalData2->GETPROPERTY, REF_SEARCH_RESULT = oSearchResult2 IF ~OBJ_VALID(oSearchResult2) THEN $ MESSAGE, "A FESTIVAL_DATA object with an invalid associated FESTIVAL_SEARCH_RESULT object was found" oSearchResult2->SETPROPERTY, FESTIVAL_DATA = self RETURN, !TRUE END PRO FESTIVAL_DATA::RESETFILTEREDIMAGE self._pFilteredImage = PTR_NEW() END PRO FESTIVAL_DATA::RESETENHANCEDPROJECTEDIMAGE self._oProjectedImage = OBJ_NEW() END PRO FESTIVAL_DATA::RESETENHANCEDIMAGE self._pEnhancedImage = PTR_NEW() END PRO FESTIVAL_DATA::RESETFITSHEADER self._pFITSHeader = PTR_NEW() END PRO FESTIVAL_DATA::RESETCALIBRATEDIMAGE self._pCalibratedImage = PTR_NEW() END PRO FESTIVAL_DATA::RESETFILTERINGSEQUENCE self._pFilteringSequence = PTR_NEW() END PRO FESTIVAL_DATA::RESETPROJCOORD self._pProjCoord = PTR_NEW() END PRO FESTIVAL_DATA::RESETMASKOFNONMISSING self._pContourOfNonMissing = PTR_NEW() END PRO FESTIVAL_DATA::RESETPROJECTEDUSERDEFINEDMASKCOORD self._pProjectedUserDefinedMaskCoord = PTR_NEW() END ;+ ; NAME: ; FESTIVAL_DATA::COPY ; ; PURPOSE: ; Copy this object to a new object. ; ; INPUTS: ; None ; ; KEYWORD PARAMETERS: ; ; WITH_FILTERED_IMAGE : also copies the _pFilteredImage buffer. ; ; WITH_ENHANCED_PROJECTED_IMAGE : also copies the _oProjectedImage object. ; ; OUTPUTS: ; ; A copy of self. ; ; MODIFICATION HISTORY: ; 31/08/06 - IAS ORSAY ;- FUNCTION FESTIVAL_DATA::COPY, $ WITH_FILTERED_IMAGE = withFilteredImage, $ WITH_ENHANCED_PROJECTED_IMAGE = withEnhancedProjectedImage ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END IF OBJ_VALID(out) THEN $ OBJ_DESTROY, out CATCH, /CANCEL ; Return a NULL object : RETURN, OBJ_NEW() END IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> COPY" ; Create an "empty" output object : out = OBJ_NEW("FESTIVAL_DATA", DATA_ENGINE = self._oDataEngine) ; Perform copy : STRUCT_ASSIGN, self, out ; Reset fields : out->RESETFILTEREDIMAGE out->RESETENHANCEDPROJECTEDIMAGE out->RESETENHANCEDIMAGE out->RESETFITSHEADER out->RESETCALIBRATEDIMAGE out->RESETFILTERINGSEQUENCE out->RESETPROJCOORD out->RESETMASKOFNONMISSING out->RESETPROJECTEDUSERDEFINEDMASKCOORD ; Copy of filtered image is required : IF KEYWORD_SET(withFilteredImage) THEN BEGIN IF PTR_VALID(self._pFilteredImage) THEN $ out->SETPROPERTY, FILTERED = *self._pFilteredImage END IF KEYWORD_SET(withEnhancedProjectedImage) THEN BEGIN IF OBJ_VALID(self._oProjectedImage) THEN $ out->SETPROPERTY, PROJECTED_IMAGE = self._oProjectedImage END IF PTR_VALID(self._pEnhancedImage) THEN $ out->SETPROPERTY, ENHANCED = *self._pEnhancedImage IF PTR_VALID(self._pFITSHeader) THEN $ out->SETPROPERTY, FITSHEADER = *self._pFITSHeader IF PTR_VALID(self._pCalibratedImage) THEN $ out->SETPROPERTY, CALIBRATED = *self._pCalibratedImage IF PTR_VALID(self._pFilteringSequence) THEN $ out->SETPROPERTY, FILTERING_SEQUENCE = *self._pFilteringSequence IF PTR_VALID(self._pProjCoord) THEN $ out->SETPROPERTY, PROJCOORD = *self._pProjCoord IF PTR_VALID(self._pContourOfNonMissing) THEN $ out->SETPROPERTY, MASK_OF_NONMISSING = *self._pContourOfNonMissing IF PTR_VALID(self._pProjectedUserDefinedMaskCoord) THEN $ out->SETPROPERTY, PROJECTION_MASK = *self._pProjectedUserDefinedMaskCoord ; Return copy : RETURN, out END ;+ ; NAME: ; FESTIVAL_DATA::UPDATESIZEINMEMORY ; ; PURPOSE: ; Update object size in memory. ; ; INPUTS: ; None ; ; KEYWORD PARAMETERS: ; None ; ; OUTPUTS: ; None ; ; MODIFICATION HISTORY: ; 30/08/06 - IAS ORSAY ;- PRO FESTIVAL_DATA::UPDATESIZEINMEMORY self._sizeInMemory = 0L IF PTR_VALID(self._pCalibratedImage) THEN $ self._sizeInMemory = self._sizeInMemory + 4*N_ELEMENTS(*self._pCalibratedImage) IF PTR_VALID(self._pFilteredImage) THEN $ self._sizeInMemory = self._sizeInMemory + 4*N_ELEMENTS(*self._pFilteredImage) IF PTR_VALID(self._pEnhancedImage) THEN $ self._sizeInMemory = self._sizeInMemory + N_ELEMENTS(*self._pEnhancedImage) ; Get FAST_DISPLAY mode : self._oDataEngine->GETPROPERTY, SELECTION_GUI = oSelectionGUI IF ~OBJ_VALID(oSelectionGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SELECTION_GUI object was found" oSelectionGUI->GETPROPERTY, SYSTEM_OPTIONS_WIZARD = oSystemGUI IF ~OBJ_VALID(oSystemGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SYSTEM_GUI object was found" oSystemGUI->GETPROPERTY, FAST_DISPLAY = fastDisplay, $ REMOVE_FILTERED_IMAGES_FROM_STACK = removeFilteredImagesFromStack IF OBJ_VALID(self._oProjectedImage) AND PTR_VALID(self._pFilteredImage) THEN BEGIN self._sizeInMemory = self._sizeInMemory + N_ELEMENTS(*self._pFilteredImage) IF fastDisplay THEN $ self._sizeInMemory = self._sizeInMemory*2 ENDIF IF removeFilteredImagesFromStack THEN BEGIN IF OBJ_VALID(self._oProjectedImage) AND ~PTR_VALID(self._pFilteredImage) THEN BEGIN self._oProjectedImage -> getproperty, DIMENSIONS = dims self._sizeInMemory = dims[0]*dims[1] IF fastDisplay THEN $ self._sizeInMemory = self._sizeInMemory*5 ENDIF ENDIF IF !DEBUG EQ !TRUE THEN $ PRINT, "------------------------------------------------------------------------------------> Size of object in memory : " + STRTRIM(STRING(self._sizeInMemory), 2) END ;+ ; NAME: ; FESTIVAL_DATA::CLEAN_BEFORE_PUSH ; ; PURPOSE: ; Destroy object properties that don't need to be stored in the history stack. ; ; INPUTS: ; None ; ; KEYWORD PARAMETERS: ; None ; ; OUTPUTS: ; None ; ; MODIFICATION HISTORY: ; 30/08/06 - IAS ORSAY ;- PRO FESTIVAL_DATA::CLEAN_BEFORE_PUSH ; Get FAST_DISPLAY mode : self._oDataEngine->GETPROPERTY, SELECTION_GUI = oSelectionGUI IF ~OBJ_VALID(oSelectionGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SELECTION_GUI object was found" oSelectionGUI->GETPROPERTY, SYSTEM_OPTIONS_WIZARD = oSystemGUI IF ~OBJ_VALID(oSystemGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SYSTEM_GUI object was found" oSystemGUI->GETPROPERTY, REMOVE_FILTERED_IMAGES_FROM_STACK = removeFilteredImagesFromStack ; Free _pCalibratedImage : IF PTR_VALID(self._pCalibratedImage) THEN $ PTR_FREE, self._pCalibratedImage ; Free _pEnhancedImage : IF PTR_VALID(self._pEnhancedImage) THEN $ PTR_FREE, self._pEnhancedImage ; If specified by user, free _pFilteredImage : IF removeFilteredImagesFromStack THEN $ IF PTR_VALID(self._pFilteredImage) THEN $ PTR_FREE, self._pFilteredImage ; Update size in memory : self->UPDATESIZEINMEMORY END ;+ ; NAME: ; FESTIVAL_DATA::CLEAN_BEFORE_PUSH ; ; PURPOSE: ; Destroy object properties that don't need to be stored in the history stack. ; ; INPUTS: ; None ; ; KEYWORD PARAMETERS: ; None ; ; OUTPUTS: ; None ; ; MODIFICATION HISTORY: ; 30/08/06 - IAS ORSAY ;- PRO FESTIVAL_DATA::CLEAN_BEFORE_PUSH ; Get FAST_DISPLAY mode : self._oDataEngine->GETPROPERTY, SELECTION_GUI = oSelectionGUI IF ~OBJ_VALID(oSelectionGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SELECTION_GUI object was found" oSelectionGUI->GETPROPERTY, SYSTEM_OPTIONS_WIZARD = oSystemGUI IF ~OBJ_VALID(oSystemGUI) THEN $ MESSAGE, "An invalid FESTIVAL_SYSTEM_GUI object was found" oSystemGUI->GETPROPERTY, REMOVE_FILTERED_IMAGES_FROM_STACK = removeFilteredImagesFromStack ; Free _pCalibratedImage : IF PTR_VALID(self._pCalibratedImage) THEN $ PTR_FREE, self._pCalibratedImage ; Free _pEnhancedImage : IF PTR_VALID(self._pEnhancedImage) THEN $ PTR_FREE, self._pEnhancedImage ; If specified by user, free _pFilteredImage : IF removeFilteredImagesFromStack THEN $ IF PTR_VALID(self._pFilteredImage) THEN $ PTR_FREE, self._pFilteredImage ; Update size in memory : self->UPDATESIZEINMEMORY END FUNCTION FESTIVAL_DATA::ROTATE, oFestivalProjCoordGUI ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL RETURN, !FALSE END IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> ROTATE" ; An invalid object was passed : IF ~OBJ_VALID(oFestivalProjCoordGUI) THEN $ MESSAGE, "An invalid FESTIVAL_PROJCOORD_GUI object was passed" ; A wrong object was passed : IF ~OBJ_ISA(oFestivalProjCoordGUI, "FESTIVAL_PROJCOORD_GUI") THEN $ MESSAGE, "An invalid FESTIVAL_PROJCOORD_GUI object was passed" ; Check FITS header availability : IF ~PTR_VALID(self._pFITSHeader) THEN $ MESSAGE, "No valid FITS header is associated to that image" ; Check _pCalibratedImage buffer : IF ~PTR_VALID(self._pCalibratedImage) THEN $ MESSAGE, "No valid calibrated image available" ; Check projection/coordinates property validity : IF ~PTR_VALID(self._pProjCoord) THEN $ MESSAGE, "Invalid _pProjCoord property" IF ~PTR_VALID(self._pFITSHeader) THEN $ MESSAGE, "No valid FITS header available" ; Check requested coordinate system : ; Get object properties : oFestivalProjCoordGUI->GETPROPERTY, ALL = all ; Get target structure : projCoordStruct = all[self._probe] ; Default value for rotated buffer : rotated = *self._pCalibratedImage ; Compare coordinate systems : CASE projCoordStruct._coordSystem OF !HELIOCENTRIC_SOLAR_NORTH_UP: rotAngle = self._SolarNorthAngle*!DDTOR !HELIOCENTRIC_ECLIPTIC: BEGIN ;Computes direction of ecliptic north in local instrument heliocentric frame dk = self._EclipticSolarNorthAngle*!DDTOR ecl_lat = ASIN(self._haez / SQRT(self._haex^2.0d + self._haey^2.0d + self._haez^2.0d)) ;observer ecliptic latitutde x = COS(ecl_lat)*COS(dk) ;coordinates of ecliptic north rotated in heliocentric frame y = COS(ecl_lat)*SIN(dk) z = -SIN(ecl_lat) lon = ATAN(y, z) - self._CRVAL1*!DDTOR ;conversion to instrument frame COSlat = COS(ASIN(x)) y = COSlat*SIN(lon) x = TEMPORARY(x)*COS(self._CRVAL2*!DDTOR) - COSlat*COS(lon)*SIN(self._CRVAL2*!DDTOR) rotAngle = self._SolarNorthAngle*!DDTOR + ATAN(x, y) - !DPI/2.0 END ELSE: MESSAGE, "Unknown coordinate system" END ; Computes rotation. ; IF ABS(rotAngle) GT !ROTATION_THRESHOLD_ANGLE*!DDTOR THEN BEGIN img_size = SIZE(rotated) nx = img_size[1] ny = img_size[2] xc = nx/2.0 yc = ny/2.0 dq = self._CRVAL1*!DDTOR dp = self._CRVAL2*!DDTOR CASE projCoordStruct._coordSystem OF !HELIOCENTRIC_SOLAR_NORTH_UP: !HELIOCENTRIC_ECLIPTIC: BEGIN ;dk = self._EclipticSolarNorthAngle*!DDTOR defined above z = COS(dp)*COS(dq) yp = COS(dp)*SIN(dq) xp = SIN(dp) x = xp*COS(dk) - yp*SIN(dk) y = xp*SIN(dk) + yp*COS(dk) dp = ASIN(x) dq = ATAN(y, z) END ELSE: MESSAGE, "Unknown coordinate system" END ;IF !FULL_ROTATION_ACCURACY[self._PROBE, self._INSTRUMENT] EQ !TRUE THEN BEGIN IF projCoordStruct._Instrument[self._Instrument] EQ !TRUE THEN BEGIN plon = (self._CDELT1/self._SunDistNormalization)*([0, nx-1, xc, xc] - self._CRPIX1)*!DDTOR/3600.0 plat = (self._CDELT2/self._SunDistNormalization)*([yc, yc, 0, ny-1] - self._CRPIX2)*!DDTOR/3600.0 zp = COS(plat)*COS(plon) yp = COS(plat)*SIN(plon) xp = SIN(plat) x = xp*COS(rotAngle) + yp*SIN(rotAngle) y = -xp*SIN(rotAngle) + yp*COS(rotAngle) xp = x*COS(dp) + zp*SIN(dp) zp = -x*SIN(dp) + TEMPORARY(zp)*COS(dp) plon = ATAN(yp, zp) + dq plat = ASIN(xp) lonmin = MIN(plon) lonmax = MAX(plon) latmin = MIN(plat) latmax = MAX(plat) ; Updates image coordinates self._imageCoordinates = [lonmin, latmin, lonmax, latmax]*!DRADEG lon = lonmin + (lonmax - lonmin)*FINDGEN(nx)/nx - dq lat = latmin + (latmax - latmin)*FINDGEN(ny)/ny COSLon = COS(lon) # REPLICATE(1.0, ny) ;matrices of longitudes/latitudes SINLon = SIN(lon) # REPLICATE(1.0, ny) COSLat = REPLICATE(1.0, nx) # COS(lat) SINLat = REPLICATE(1.0, nx) # SIN(lat) z = COSLat*COSLon ;rotation in longitude y = TEMPORARY(COSLat)*TEMPORARY(SINLon) xp = SINLat*COS(dp) - z*SIN(dp) ;rotation in latitude z = TEMPORARY(SINLat)*SIN(dp) + TEMPORARY(z)*COS(dp) x = xp*COS(rotAngle) - y*SIN(rotAngle) ;rotation around local Z axis y = TEMPORARY(xp)*SIN(rotAngle) + TEMPORARY(y)*COS(rotAngle) SWITCH self._probe OF ;conversion to pixels (with distortion correction or not) !SOHO: BEGIN SWITCH self._INSTRUMENT OF !EIT: !NRH: !MK4: !TRACE: !XRT: !C1: BEGIN rotated = INTERPOLATE(TEMPORARY(rotated), $ self._CRPIX1 + 3600.0*ATAN(y, z)*!DRADEG/(self._CDELT1/self._SunDistNormalization), $ self._CRPIX2 + 3600.0*ASIN(x)*!DRADEG/(self._CDELT2/self._SunDistNormalization), $ MISSING = !MISSING_VALUE) BREAK END !C2: !C3: BEGIN IF self._INSTRUMENT EQ !C2 THEN $ Cf = [-9.5479180d-015, 1.0051345, -7.8216544d-011, -16.209086] $ ELSE $ Cf = [-5.3290705d-015, 0.98483431, -1.8189894d-012, 0.98990313] plate = !DDTOR*(self._CDELT1/self._SunDistNormalization)/3600.0 ;radians/pixel theta = ACOS(z) phi = ATAN(x, y) rho = Cf[0] + theta*(Cf[1] + theta*(Cf[2] + theta*Cf[3])) rotated = INTERPOLATE(TEMPORARY(rotated), $ self._CRPIX1 + rho * COS(phi) / plate, $ self._CRPIX2 + rho * SIN(phi) / plate, $ MISSING = !MISSING_VALUE) BREAK END ; Undefined : ELSE: MESSAGE, "Unknown SOHO instruments" ENDSWITCH BREAK END !STEREOA: !STEREOB: BEGIN SWITCH self._INSTRUMENT OF !EUVI: !COR1: BEGIN rotated = INTERPOLATE(TEMPORARY(rotated), $ self._CRPIX1 + 3600.0*ATAN(y, z)*!DRADEG/(self._CDELT1/self._SunDistNormalization), $ self._CRPIX2 + 3600.0*ASIN(x)*!DRADEG/(self._CDELT2/self._SunDistNormalization), $ MISSING = !MISSING_VALUE) BREAK END !COR2: BEGIN IF self._Probe EQ !STEREOA THEN $ ; COR2A coeffs (pixels) Cf = [1.7505732e-005,1.0080725, -0.15074487, 0.045028273, -0.015651654] $ ELSE $ Cf = [-0.00034103570, 1.0207708, -0.29248398, 0.16572936, -0.098049484] plate = !DDTOR*(self._CDELT1/self._SunDistNormalization)/3600.0 ;radians/pixel theta = ACOS(z) phi = ATAN(x, y) rho = Cf[0] + theta*(Cf[1] + theta*(Cf[2] + theta*(Cf[3] + theta*Cf[4]))) rotated = INTERPOLATE(TEMPORARY(rotated), $ self._CRPIX1 + rho * COS(phi) / plate, $ self._CRPIX2 + rho * SIN(phi) / plate, $ MISSING = !MISSING_VALUE) BREAK END !HI1: !HI2: BEGIN plate = !DDTOR*(self._CDELT1/self._SunDistNormalization)/3600.0 ;radians/pixel mu = (*self._pFITSHeader).PV2_1 distortion = (mu + 1.0)/(mu + z) ;distortion = (mu + 1.0)*SIN(theta)/(mu + COS(theta)) rotated = INTERPOLATE(TEMPORARY(rotated), $ self._CRPIX1 + distortion * y / plate, $ self._CRPIX2 + distortion * x / plate, $ MISSING = !MISSING_VALUE) BREAK END ; Undefined : ELSE: MESSAGE, "Unknown STEREO instruments" ENDSWITCH BREAK END ; Undefined : ELSE: MESSAGE, "Unknown probe" ENDSWITCH ENDIF ELSE BEGIN xs = self._CRPIX1 - 3600.0*self._CRVAL1/(self._CDELT1/self._SunDistNormalization) - xc ys = self._CRPIX2 - 3600.0*self._CRVAL2/(self._CDELT2/self._SunDistNormalization) - yc SunX = xs*COS(rotAngle) - ys*SIN(rotAngle) + xc SunY = xs*SIN(rotAngle) + ys*COS(rotAngle) + yc self._imageCoordinates = [-SunX*self._CDELT1/self._SunDistNormalization, -SunY*self._CDELT2/self._SunDistNormalization, $ (nx - SunX)*self._CDELT1/self._SunDistNormalization, (ny - SunY)*self._CDELT2/self._SunDistNormalization]/3600. rotated = ROT(TEMPORARY(rotated), -rotAngle*!DRADEG, 1.0, xc, yc, /INTERP, /PIVOT, MISSING = !MISSING_VALUE) ENDELSE ;ENDIF CASE projCoordStruct._coordSystem OF !HELIOCENTRIC_SOLAR_NORTH_UP: BEGIN IF !DEBUG EQ !TRUE THEN $ ;IF ABS(rotAngle) GT !ROTATION_THRESHOLD_ANGLE THEN $ PRINT, "****** Image Rotated to Solar north up ", rotAngle, " degrees" ; Set object property : (*self._pProjCoord)._coordSystem = !HELIOCENTRIC_SOLAR_NORTH_UP END !HELIOCENTRIC_ECLIPTIC: BEGIN IF !DEBUG EQ !TRUE THEN $ ;IF ABS(rotAngle) GT !ROTATION_THRESHOLD_ANGLE THEN $ PRINT, "****** Image Rotated to Ecliptic north up ", rotAngle, " degrees" ; Set object property : (*self._pProjCoord)._coordSystem = !HELIOCENTRIC_ECLIPTIC END ELSE: MESSAGE, "Unknown coordinate system" END ; Rotation could not be performed : IF N_ELEMENTS(rotated) EQ 0 THEN $ MESSAGE, "Rotated image could not be computed" ; Update _pCalibrated property : *self._pCalibratedImage = rotated RETURN, !TRUE END ;+ ; NAME: ; FESTIVAL_DATA::DATA_PREP ; ; PURPOSE: ; Perform calibration on an image depending on probe/instrument. ; ; INPUTS: ; oFestivalCalibrationGUI: an object reference to the FESTIVAL_CALIBRATION_GUI wizard. ; ; KEYWORD PARAMETERS: ; None. ; ; OUTPUTS: ; 1 if calibration could be performed OK, 0 otherwise. ; ; MODIFICATION HISTORY: ; 29/08/06 - IAS ORSAY ;- FUNCTION FESTIVAL_DATA::DATA_PREP, oFestivalCalibrationGUI ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, "WARNING : " + !error_state.msg END CATCH, /CANCEL ; Reinitialize some object properties : ; Calibrated buffer : IF PTR_VALID(self._pCalibratedImage) THEN $ PTR_FREE, self._pCalibratedImage ; FITS header : IF PTR_VALID(self._pFITSHeader) THEN $ PTR_FREE, self._pFITSHeader ; Calibration model : self._calibrationArray._calibrationModel = !OFF self._calibrationArray._desmear = !OFF ; Image coordinates : self._imageCoordinates = [0.0, 0.0, 0.0, 0.0] ; Update size in memory : self->UPDATESIZEINMEMORY RETURN, !FALSE END IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> DATA_PREP" ; Return value : out = !TRUE ; An invalid object was passed : IF ~OBJ_VALID(oFestivalCalibrationGUI) THEN $ MESSAGE, "An invalid FESTIVAL_CALIBRATION_GUI object was passed" ; A wrong object was passed : IF ~OBJ_ISA(oFestivalCalibrationGUI, "FESTIVAL_CALIBRATION_GUI") THEN $ MESSAGE, "An invalid FESTIVAL_CALIBRATION_GUI object was passed" oFestivalCalibrationGUI->GETPROPERTY, ALL = all, PARENT = oParent IF ~OBJ_VALID(oParent) THEN $ MESSAGE, "An invalid FESTIVAL_SELECTION_GUI object was found" IF ~OBJ_ISA(oParent, "FESTIVAL_SELECTION_GUI") THEN $ MESSAGE, "An invalid FESTIVAL_SELECTION_GUI object was found" ; functions defined in other files and ; that need to be declared as functions to the compiler FORWARD_FUNCTION EIT_FXPAR, EIT_PIXSIZE, EIT_POINT, GET_ORBIT, $ SCC_GETBKGIMG, COR_POLARIZ ; Probe testing : SWITCH self._probe OF ; SOHO probe : !SOHO: BEGIN if !DEBUG EQ !TRUE then begin print, "preping :"+self._fullfilepath[0] endif ; Instrument testing : SWITCH self._instrument OF !EIT: BEGIN ; mod by A. Antunes to allow ; catalog_lz usage ; at NRL-- eit_prep requires the /nrl flag if (getenv('SITE') eq 'nrl') then nrl=1 else nrl=0 EIT_PREP, self._fullfilepath[0], hdr, image, nrl=nrl, /NO_ROLL, $ NO_CALIBRATE = (all[self._probe, self._instrument]._on EQ !OFF), VERBOSE = !DEBUG ; Perform error checking : IF N_ELEMENTS(image) EQ 0 OR N_ELEMENTS(hdr) EQ 0 THEN $ MESSAGE, "Calibration could not be performed for : " + self._fileSpecification IF (self._userFilter EQ !UNDEF_FIELD) OR (self._userFilter EQ '') THEN BEGIN self._userFilter = STRTRIM(EIT_FXPAR(hdr, 'FILTER'), 2) IF self._userFilter EQ 'Al +1' THEN self._userFilter = 'Al+1' IF self._userFilter EQ 'Al +2' THEN self._userFilter = 'Al+2' ENDIF ; Update _calibrationModel property : self._calibrationArray = all[self._probe, self._instrument] ; Update _imageCoordinates property : P1_X = EIT_FXPAR(hdr, 'P1_X') - 1 P1_Y = EIT_FXPAR(hdr, 'P1_Y') - 20 P2_X = EIT_FXPAR(hdr, 'P2_X') - 1 P2_Y = EIT_FXPAR(hdr, 'P2_Y') - 20 xpix = EIT_FXPAR(hdr, 'NAXIS1') ypix = EIT_FXPAR(hdr, 'NAXIS2') binx = ((P2_X - P1_X + 1)/xpix)>1 biny = ((P2_Y - P1_Y + 1)/ypix)>1 ; Normalize to binning image = TEMPORARY(image)/(binx*biny) self._CDELT1 = EIT_FXPAR(hdr, 'CDELT1') self._CDELT2 = EIT_FXPAR(hdr, 'CDELT2') IF self._CDELT1 EQ 0 THEN self._CDELT1 = EIT_PIXSIZE()*binx IF self._CDELT2 EQ 0 THEN self._CDELT2 = EIT_PIXSIZE()*biny self._CRPIX1 = EIT_FXPAR(hdr, 'CRPIX1') self._CRPIX2 = EIT_FXPAR(hdr, 'CRPIX2') ; mod by A. Antunes to allow catalog_lz usage at NRL, keyname used for ; both eit_point and get_orbit as 'CORRECTED DATE_OBS' does not exist ; in NRL FITS files if (nrl EQ 1) then date_keyname='DATE_OBS' $ else date_keyname='CORRECTED DATE_OBS' IF (self._CRPIX1 LT 0) OR (self._CRPIX2 LT 0) THEN BEGIN point = EIT_POINT(EIT_FXPAR(hdr,date_keyname, image_no=0), $ EIT_FXPAR(HDR, 'WAVELNTH', image_no=0), BIN=binx) self._CRPIX1 = point[0] - P1_X self._CRPIX2 = point[1] - P1_Y END self._CRVAL1 = FLOAT(EIT_FXPAR(hdr, 'CRVAL1'))/3600.0 self._CRVAL2 = FLOAT(EIT_FXPAR(hdr, 'CRVAL2'))/3600.0 ; Extract Geometry information from header errmsg = '' date = EIT_FXPAR(hdr, date_keyname) orbit = GET_ORBIT(date, errmsg=errmsg) IF (errmsg EQ '') AND TEST_ORBIT(orbit) THEN BEGIN self._HAEX = orbit.HEC_X*1000.0d self._HAEY = orbit.HEC_Y*1000.0d self._HAEZ = orbit.HEC_Z*1000.0d self._CarringtonLongitude = (orbit.HEL_LON_SOHO*!DRADEG) MOD 360 self._CarringtonLatitude = orbit.HEL_LAT_SOHO*!DRADEG self._SunDist = SQRT(self._HAEX^2.0 + self._HAEY^2.0 + self._HAEZ^2.0) ENDIF ELSE BEGIN ; Computes geometry information: 1% correction from Earth view dum = GET_SUN(date, HE_LON=hel_lon, HE_LAT=hel_lat) alpha = !DDTOR*360.0*dum[6]/24.0 ;RA delta = !DDTOR*dum[7] ;DEC epsilon = 23.4392911*!DDTOR ;inclination of the ecliptic (J2000) beta = -ASIN(SIN(delta)*COS(epsilon) - COS(delta)*SIN(epsilon)*SIN(alpha)) ;ecliptic latitude of Earth as seen from Sun lambda = !dpi + ATAN(SIN(epsilon)*SIN(delta) + SIN(alpha)*COS(delta)*COS(epsilon), COS(alpha)*COS(delta)) ;ecliptic longitude of Earth as seen from Sun SunDist = !MEAN_SUN_SOHO_EARTH_DISTANCE_RATIO*dum[0]*!ONE_ASTRONOMICAL_UNIT ;1% correction for SOHO self._HAEX = SunDist*COS(beta)*COS(lambda) self._HAEY = SunDist*COS(beta)*SIN(lambda) self._HAEZ = SunDist*SIN(beta) self._CarringtonLongitude = hel_lon MOD 360 self._CarringtonLatitude = hel_lat self._SunDist = SunDist ENDELSE self._SunDistNormalization = 1.0d self._SolarNorthAngle = -(FLOAT(EIT_FXPAR(hdr, 'SC_ROLL')) MOD 360) self._EclipticSolarNorthAngle = FESTIVAL_ECL_SOLAR_NORTH(self._HAEX, self._HAEY, self._HAEZ) BREAK END !C1: !C2: !C3: BEGIN IF all[self._probe, self._instrument]._calibrationModel EQ !OFF THEN $ LASCO_PREP, self._fullfilepath[0], hdr, image, /MASK_OCC, /NORECTIFY, SUNC = sunc, ROLL = roll ELSE $ LASCO_PREP, self._fullfilepath[0], hdr, image, /MASK_OCC, /NORECTIFY, SUNC = sunc, ROLL = roll, $ USE_MODEL = all[self._probe, self._instrument]._calibrationModel ; Perform error checking : IF N_ELEMENTS(image) EQ 0 OR N_ELEMENTS(hdr) EQ 0 THEN $ MESSAGE, "Calibration could not be performed for : " + self._fileSpecification IF (self._userWave EQ !UNDEF_FIELD) OR (self._userWave EQ '') THEN $ self._userWave = hdr.filter IF (self._userFilter EQ !UNDEF_FIELD) OR (self._userFilter EQ '') THEN $ self._userFilter = hdr.polar ; Update _calibrationModel property : self._calibrationArray = all[self._probe, self._instrument] ; Update _imageCoordinates property : binx = hdr.LEBXSUM biny = hdr.LEBYSUM P1_Y = hdr.P1COL - 20 P2_Y = hdr.P2COL - 20 P1_X = hdr.P1ROW - 1 P2_X = hdr.P2ROW - 1 self._CRPIX1 = sunc.xcen self._CRPIX2 = sunc.ycen self._CDELT1 = hdr.CDELT1 self._CDELT2 = hdr.CDELT2 self._CRVAL1 = 0.0 self._CRVAL2 = 0.0 ; Extract Geometry information from header errmsg = '' date = hdr.DATE_OBS + ' ' + hdr.TIME_OBS orbit = GET_ORBIT(date, errmsg=errmsg) IF (errmsg EQ '') AND TEST_ORBIT(orbit) THEN BEGIN self._HAEX = orbit.HEC_X*1000.0d self._HAEY = orbit.HEC_Y*1000.0d self._HAEZ = orbit.HEC_Z*1000.0d self._CarringtonLongitude = (orbit.HEL_LON_SOHO*!DRADEG) MOD 360 self._CarringtonLatitude = orbit.HEL_LAT_SOHO*!DRADEG self._SunDist = SQRT(self._HAEX^2.0 + self._HAEY^2.0 + self._HAEZ^2.0) ENDIF ELSE BEGIN ; Computes geometry information: 1% correction from Earth view dum = GET_SUN(date, HE_LON=hel_lon, HE_LAT=hel_lat) alpha = !DDTOR*360.0*dum[6]/24.0 ;RA delta = !DDTOR*dum[7] ;DEC epsilon = 23.4392911*!DDTOR ;inclination of the ecliptic (J2000) beta = -ASIN(SIN(delta)*COS(epsilon) - COS(delta)*SIN(epsilon)*SIN(alpha)) ;ecliptic latitude of Earth as seen from Sun lambda = !dpi + ATAN(SIN(epsilon)*SIN(delta) + SIN(alpha)*COS(delta)*COS(epsilon), COS(alpha)*COS(delta)) ;ecliptic longitude of Earth as seen from Sun SunDist = !MEAN_SUN_SOHO_EARTH_DISTANCE_RATIO*dum[0]*!ONE_ASTRONOMICAL_UNIT ;1% correction for SOHO self._HAEX = SunDist*COS(beta)*COS(lambda) self._HAEY = SunDist*COS(beta)*SIN(lambda) self._HAEZ = SunDist*SIN(beta) self._CarringtonLongitude = hel_lon MOD 360 self._CarringtonLatitude = hel_lat self._SunDist = SunDist ENDELSE self._SunDistNormalization = 1.0d self._SolarNorthAngle = !DRADEG * roll self._EclipticSolarNorthAngle = FESTIVAL_ECL_SOLAR_NORTH(self._HAEX, self._HAEY, self._HAEZ) BREAK END ; *** ADDED FOR NRH *** !NRH : BEGIN ; by definition, self._fullFilePath is ; a strarr(3) but only first component ; makes sense here MREADFITS, self._fullFilePath[0], hdr, image, /QUIET ; Perform error checking : IF N_ELEMENTS(image) EQ 0 OR N_ELEMENTS(hdr) EQ 0 THEN $ MESSAGE, "Calibration could not be performed for : " + self._fileSpecification ; Update _calibrationModel property : self._calibrationArray = all[self._probe, self._instrument] ; Update _imageCoordinates property : self._CRPIX1 = hdr.CRPIX1 - 1.0 self._CRPIX2 = hdr.CRPIX2 - 1.0 self._CDELT1 = hdr.CDELT1 self._CDELT2 = hdr.CDELT2 self._CRVAL1 = 0.0 self._CRVAL2 = 0.0 ; Computes geometry information for Earth view dum = GET_SUN(hdr.DATE_OBS, HE_LON=hel_lon, HE_LAT=hel_lat) alpha = !DDTOR*360.0*dum[6]/24.0 ;RA delta = !DDTOR*dum[7] ;DEC epsilon = 23.4392911*!DDTOR ;inclination of the ecliptic (J2000) beta = -ASIN(SIN(delta)*COS(epsilon) - COS(delta)*SIN(epsilon)*SIN(alpha)) ;ecliptic latitude of Earth as seen from Sun lambda = !dpi + ATAN(SIN(epsilon)*SIN(delta) + SIN(alpha)*COS(delta)*COS(epsilon), COS(alpha)*COS(delta)) ;ecliptic longitude of Earth as seen from Sun SunDist = dum[0]*!ONE_ASTRONOMICAL_UNIT self._HAEX = SunDist*COS(beta)*COS(lambda) self._HAEY = SunDist*COS(beta)*SIN(lambda) self._HAEZ = SunDist*SIN(beta) self._CarringtonLongitude = hel_lon MOD 360 self._CarringtonLatitude = hel_lat self._SunDist = SunDist self._SunDistNormalization = !MEAN_SUN_SOHO_EARTH_DISTANCE_RATIO self._SolarNorthAngle = 0 ;By definition NRH data have solar north up self._EclipticSolarNorthAngle = FESTIVAL_ECL_SOLAR_NORTH(self._HAEX, self._HAEY, self._HAEZ) BREAK END ; *** END OF ADDED FOR NRH *** ; *** ADDED FOR Mk4 *** !Mk4 : BEGIN ; by definition, self._fullFilePath is ; a strarr(3) but only first component ; makes sense here extension = strmid(self._fullFilePath[0], 1, /REVERSE ) if (extension EQ 'gz') THEN BEGIN new_file = !MK4_UNZIPPED_DIR + $ PATH_SEP() + file_basename(self._fullFilePath[0]) file_copy, self._fullFilePath[0], new_file, /OVERWRITE if (os_family(/lower) eq 'unix') then $ gzip, new_file, unzipped_file, /UNZIP $ else begin ; Windows case (not supported by $SSW/gen/idl/system/gzip.pro) : ; gzip.exe must be in PATH (it can be downloaded at : ; http://www.gzip.org/ ) gunzip_cmd = 'gzip -d -f "'+new_file+'"' espawn,gunzip_cmd,out_txt,/noshell if (out_txt[0] NE '') then begin print,"------------------------------------------------------------------------------------" print,"Have you really installed gzip (from http://www.gzip.org/) and put it in the Path variable?" print,out_txt print,"------------------------------------------------------------------------------------" endif unzipped_file=str_replace(new_file,'.gz','') endelse self._fullFilePath[0] = unzipped_file endif mreadfits, self._fullFilePath[0], hdr, image, /QUIET ; Perform error checking : IF N_ELEMENTS(image) EQ 0 OR N_ELEMENTS(hdr) EQ 0 THEN $ MESSAGE, "Calibration could not be performed for : " + self._fileSpecification bad = WHERE(image EQ -32000, count) IF count GT 0 THEN image[bad] = !MISSING_VALUE ; Update _calibrationModel property : self._calibrationArray = all[self._probe, self._instrument] ; Update _imageCoordinates property : self._CRPIX1 = hdr.CRPIX1 - 1.0 self._CRPIX2 = hdr.CRPIX2 - 1.0 self._CDELT1 = hdr.CDELT1 self._CDELT2 = hdr.CDELT2 self._CRVAL1 = hdr.CRVAL1 self._CRVAL2 = hdr.CRVAL1 ; Computes geometry information for Earth view dum = GET_SUN(hdr.DATE_OBS, HE_LON=hel_lon, HE_LAT=hel_lat) alpha = !DDTOR*360.0*dum[6]/24.0 ;RA delta = !DDTOR*dum[7] ;DEC epsilon = 23.4392911*!DDTOR ;inclination of the ecliptic (J2000) beta = -ASIN(SIN(delta)*COS(epsilon) - COS(delta)*SIN(epsilon)*SIN(alpha)) ;ecliptic latitude of Earth as seen from Sun lambda = !dpi + ATAN(SIN(epsilon)*SIN(delta) + SIN(alpha)*COS(delta)*COS(epsilon), COS(alpha)*COS(delta)) ;ecliptic longitude of Earth as seen from Sun SunDist = dum[0]*!ONE_ASTRONOMICAL_UNIT self._HAEX = SunDist*COS(beta)*COS(lambda) self._HAEY = SunDist*COS(beta)*SIN(lambda) self._HAEZ = SunDist*SIN(beta) self._CarringtonLongitude = hel_lon MOD 360 self._CarringtonLatitude = hel_lat self._SunDist = SunDist self._SunDistNormalization = !MEAN_SUN_SOHO_EARTH_DISTANCE_RATIO self._SolarNorthAngle = 0 ;By definition NRH data have solar north up self._EclipticSolarNorthAngle = FESTIVAL_ECL_SOLAR_NORTH(self._HAEX, self._HAEY, self._HAEZ) BREAK END ; *** END OF ADDED FOR Mk4 *** ; *** ADDED FOR TRACE *** !TRACE : BEGIN self._oRefSearchResult-> GetProperty, INDEX_IN_FILE = index_in_file, $ DATE = date_obs ; case of TRACE files downloaded with VSO is ; different because index of data in ; file is not known yet : first look ; for the index of that date. ; Note : 128x128 images are only accepted ; when no bigger data at that date is found if (index_in_file EQ -1) then begin read_trace, self._fullFilePath[0], -1, headers good_files_index = where(headers.DATE_OBS EQ date_obs, count) if (count EQ 0) then begin MESSAGE, "Calibration could not be performed for : " + self._fileSpecification endif index_in_file = good_files_index[0] self._oRefSearchResult-> SetProperty, INDEX_IN_FILE = index_in_file endif no_calibrate = all[self._probe, self._instrument]._on EQ !OFF TRACE_PREP, self._fullFilePath[0], index_in_file, hdr, image, $ NO_DARKSUB = no_calibrate, $ NO_FLATFIELD = no_calibrate, $ ;NO_CALIB = no_calibrate, $ NORMALIZE = ~no_calibrate, $ /WAVE2POINT_CORRECT, /QUIET, VERBOSE =!DEBUG, /FLOAT ; Perform error checking : IF N_ELEMENTS(image) EQ 0 OR N_ELEMENTS(hdr) EQ 0 THEN $ MESSAGE, "Calibration could not be performed for : " + self._fileSpecification ; bad = WHERE(image EQ -32000, count) ; IF count GT 0 THEN image[bad] = !MISSING_VALUE ; Update _calibrationModel property : self._calibrationArray = all[self._probe, self._instrument] ; Update _imageCoordinates property : self._CRPIX1 = hdr.CRPIX1 - 1.0 self._CRPIX2 = hdr.CRPIX2 - 1.0 self._CDELT1 = hdr.CDELT1 self._CDELT2 = hdr.CDELT2 self._CRVAL1 = hdr.CRVAL1 self._CRVAL2 = hdr.CRVAL1 ; Computes geometry information for Earth view dum = GET_SUN(hdr.DATE_OBS, HE_LON=hel_lon, HE_LAT=hel_lat) alpha = !DDTOR*360.0*dum[6]/24.0 ;RA delta = !DDTOR*dum[7] ;DEC epsilon = 23.4392911*!DDTOR ;inclination of the ecliptic (J2000) beta = -ASIN(SIN(delta)*COS(epsilon) - COS(delta)*SIN(epsilon)*SIN(alpha)) ;ecliptic latitude of Earth as seen from Sun lambda = !dpi + ATAN(SIN(epsilon)*SIN(delta) + SIN(alpha)*COS(delta)*COS(epsilon), COS(alpha)*COS(delta)) ;ecliptic longitude of Earth as seen from Sun SunDist = dum[0]*!ONE_ASTRONOMICAL_UNIT self._HAEX = SunDist*COS(beta)*COS(lambda) self._HAEY = SunDist*COS(beta)*SIN(lambda) self._HAEZ = SunDist*SIN(beta) self._CarringtonLongitude = hel_lon MOD 360 self._CarringtonLatitude = hel_lat self._SunDist = SunDist self._SunDistNormalization = !MEAN_SUN_SOHO_EARTH_DISTANCE_RATIO self._SolarNorthAngle = 0 self._EclipticSolarNorthAngle = FESTIVAL_ECL_SOLAR_NORTH(self._HAEX, self._HAEY, self._HAEZ) BREAK END ; *** END OF ADDED FOR TRACE *** ; *** ADDED FOR XRT *** !XRT : BEGIN self._oRefSearchResult-> GetProperty, INDEX_IN_FILE = index_in_file, $ DATE = date_obs no_calibrate = all[self._probe, self._instrument]._on EQ !OFF XRT_PREP, self._fullFilePath[0], 0, hdr, image, $ NORMALIZE = ~no_calibrate, $ /FLOAT, /QUIET, VERBOSE = !DEBUG ; Perform error checking : IF N_ELEMENTS(image) EQ 0 OR N_ELEMENTS(hdr) EQ 0 THEN $ MESSAGE, "Calibration could not be performed for : " + self._fileSpecification offsets = [0.0, 0.0] XRT_JITTER, hdr, offsets IF (self._userWave EQ !UNDEF_FIELD) OR (self._userWave EQ '') THEN $ self._userWave = hdr.EC_FW1_ IF (self._userFilter EQ !UNDEF_FIELD) OR (self._userFilter EQ '') THEN $ self._userFilter = hdr.EC_FW2_ ; Update _calibrationModel property : self._calibrationArray = all[self._probe, self._instrument] ; Update _imageCoordinates property : bin = hdr.CHIP_SUM self._CRPIX1 = (hdr.CRPIX1 - 9)/bin self._CRPIX2 = (hdr.CRPIX2 - 1)/bin default_cdelt = 1.031 ;arcseconds/pixel ;default value if header value seems too far off IF ABS(hdr.CDELT1 - default_cdelt) GT 0.001 THEN $ self._CDELT1 = default_cdelt*bin $ ELSE $ self._CDELT1 = hdr.CDELT1 IF ABS(hdr.CDELT2 - default_cdelt) GT 0.001 THEN $ self._CDELT2 = default_cdelt*bin $ ELSE $ self._CDELT2 = hdr.CDELT2 self._CRVAL1 = (hdr.CRVAL1 - offsets[0])/3600.0 self._CRVAL2 = (hdr.CRVAL2 - offsets[1])/3600.0 ; Computes geometry information for Earth view dum = GET_SUN(hdr.DATE_OBS, HE_LON=hel_lon, HE_LAT=hel_lat) alpha = !DDTOR*360.0*dum[6]/24.0 ;RA delta = !DDTOR*dum[7] ;DEC epsilon = 23.4392911*!DDTOR ;inclination of the ecliptic (J2000) beta = -ASIN(SIN(delta)*COS(epsilon) - COS(delta)*SIN(epsilon)*SIN(alpha)) ;ecliptic latitude of Earth as seen from Sun lambda = !dpi + ATAN(SIN(epsilon)*SIN(delta) + SIN(alpha)*COS(delta)*COS(epsilon), COS(alpha)*COS(delta)) ;ecliptic longitude of Earth as seen from Sun SunDist = dum[0]*!ONE_ASTRONOMICAL_UNIT self._SunDistNormalization = !MEAN_SUN_SOHO_EARTH_DISTANCE_RATIO self._HAEX = SunDist*COS(beta)*COS(lambda) self._HAEY = SunDist*COS(beta)*SIN(lambda) self._HAEZ = SunDist*SIN(beta) self._CarringtonLongitude = hel_lon MOD 360 self._CarringtonLatitude = hel_lat self._SunDist = SunDist self._SunDistNormalization = !MEAN_SUN_SOHO_EARTH_DISTANCE_RATIO self._SolarNorthAngle = hdr.CROTA1 self._EclipticSolarNorthAngle = FESTIVAL_ECL_SOLAR_NORTH(self._HAEX, self._HAEY, self._HAEZ) BREAK END ; *** END OF ADDED FOR XRT *** ; Undefined : ELSE: MESSAGE, "Unknown SOHO instruments" END BREAK END ; STEREOA probe : !STEREOA: ; STEREOB probe : !STEREOB: BEGIN SWITCH self._instrument OF !EUVI: !COR1: !COR2: !HI1: !HI2: BEGIN IF all[self._probe, self._instrument]._on THEN BEGIN CASE all[self._probe, self._instrument]._calibrationModel OF !MONTHLYMINIMUM: BEGIN calfac_off = 1 calimg_off = 1 calibrate_off = self._Instrument EQ !COR2 AND self._polarityType NE !TB daily = 0 totalb = (self._Instrument EQ !HI1 OR self._Instrument EQ !HI2) $ OR ((self._Instrument EQ !COR2) AND (self._matchedPolarity EQ !TRUE) AND (self._polarityType EQ !TB)) END !DAILYMEDIAN: BEGIN calfac_off = 1 calimg_off = 1 calibrate_off = self._Instrument EQ !COR2 AND self._polarityType NE !TB daily = 1 totalb = (self._Instrument EQ !HI1 OR self._Instrument EQ !HI2) $ OR ((self._Instrument EQ !COR2) AND (self._matchedPolarity EQ !TRUE) AND (self._polarityType EQ !TB)) END !OFF: BEGIN calfac_off = 0 calimg_off = 0 calibrate_off = 0 END ELSE: MESSAGE, 'Uknown calibration model' ENDCASE ENDIF ELSE BEGIN calfac_off = 1 calimg_off = 1 calibrate_off = 1 ENDELSE ; Create an object FESTIVAL_KEYWORD_READER : keywordsFile = !FESTIVAL_SAVE_DIRECTORY + PATH_SEP() + 'config' + PATH_SEP() + !KEYWORDS_FILE oKeywordReader = OBJ_NEW("FESTIVAL_KEYWORD_READER", keywordsFile) IF OBJ_VALID(oKeywordReader) THEN BEGIN oKeywordReader->READSECTION, 'SECCHI_PREP', RESULT = extraKwds, /CASTTOINTEGER ; Free memory : OBJ_DESTROY, oKeywordReader ENDIF ; Stereo calibration : precomm = self._instrument EQ !COR2 IF self._matchedPolarity EQ !TRUE THEN $ SECCHI_PREP, self._fullFilePath, hdr, image, CALIBRATE_OFF = calibrate_off, CALFAC_OFF = calfac_off, CALIMG_OFF = calimg_off, SILENT = (!DEBUG EQ !FALSE), $ DESMEAR_OFF = (all[self._probe, self._instrument]._desmear EQ !FALSE), /NOWARP, $ /NOSPICE, PRECOMMCORRECT_ON = precomm, /BKGIMG_OFF, _EXTRA = extraKwds $ ELSE $ SECCHI_PREP, self._fullFilePath[0], hdr, image, CALIBRATE_OFF = calibrate_off, CALFAC_OFF = calfac_off, CALIMG_OFF = calimg_off, SILENT = (!DEBUG EQ !FALSE), $ DESMEAR_OFF = (all[self._probe, self._instrument]._desmear EQ !FALSE), /NOWARP, $ /NOSPICE, PRECOMMCORRECT_ON = precomm, /BKGIMG_OFF, _EXTRA = extraKwds CASE self._Instrument OF !EUVI: BEGIN IF (self._userFilter EQ !UNDEF_FIELD) OR (self._userFilter EQ '') THEN $ self._userFilter = hdr[0].filter END !COR1: BEGIN END !COR2: BEGIN END !HI1: BEGIN END !HI2: BEGIN END ELSE: MESSAGE, "Unknown SECCHI Instrument" ENDCASE FOR i=0, N_ELEMENTS(hdr)-1 DO BEGIN CASE self._Instrument OF !EUVI: bin = 2.0^(hdr[i].SUMMED-1) !COR1: bin = 2.0^(hdr[i].SUMMED-2) !COR2: bin = 2.0^(hdr[i].SUMMED-1) !HI1: bin = 2.0^(hdr[i].SUMMED-2) !HI2: bin = 2.0^(hdr[i].SUMMED-2) ELSE: MESSAGE, "Unknown SECCHI Instrument" ENDCASE IF bin GT 1 THEN image[*, *, i] = image[*, *, i]/bin^2.0 ENDFOR IF ~((self._Instrument EQ !COR2) AND (self._matchedPolarity EQ !TRUE) AND (self._polarityType EQ !TB)) THEN BEGIN IF (all[self._probe, self._instrument]._on EQ !TRUE) AND $ (all[self._probe, self._instrument]._calibrationModel NE !OFF) THEN BEGIN FOR i=0, N_ELEMENTS(hdr)-1 DO BEGIN background = SCC_GETBKGIMG(hdr[i], TOTALB = totalb, DAILY = daily, $ SILENT = (!DEBUG EQ !FALSE), /INTERPOLATE) IF N_ELEMENTS(background) GT 1 THEN BEGIN IF self._Instrument EQ !COR2 OR self._Instrument EQ !HI1 OR self._Instrument EQ !HI2 THEN $ image[*, *, i] = image[*, *, i] / background $ ELSE $ image[*, *, i] = image[*, *, i] - background ENDIF ENDFOR ENDIF ENDIF IF self._matchedPolarity EQ !TRUE THEN BEGIN CASE self._polarityType OF !PB: image = COR_POLARIZ(image, hdr, /PB, CALIBRATE_OFF = calibrate_off, CALFAC_OFF = calfac_off, CALIMG_OFF = calimg_off, SILENT = (!DEBUG EQ !FALSE)) !TB: image = COR_POLARIZ(image, hdr, CALIBRATE_OFF = calibrate_off, CALFAC_OFF = calfac_off, CALIMG_OFF = calimg_off, SILENT = (!DEBUG EQ !FALSE)) !MU: image = COR_POLARIZ(image, hdr, /MU, CALIBRATE_OFF = calibrate_off, CALFAC_OFF = calfac_off, CALIMG_OFF = calimg_off, SILENT = (!DEBUG EQ !FALSE)) !PERCENT: image = COR_POLARIZ(image, hdr, /PERCENT, CALIBRATE_OFF = calibrate_off, CALFAC_OFF = calfac_off, CALIMG_OFF = calimg_off, SILENT = (!DEBUG EQ !FALSE)) ELSE: MESSAGE, 'Unknown polarisation' END hdr = hdr[1] ENDIF IF ((self._Instrument EQ !COR2) AND (self._matchedPolarity EQ !TRUE) AND (self._polarityType EQ !TB)) THEN BEGIN IF (all[self._probe, self._instrument]._on EQ !TRUE) AND $ (all[self._probe, self._instrument]._calibrationModel NE !OFF) THEN BEGIN background = SCC_GETBKGIMG(hdr, TOTALB = totalb, DAILY = daily, $ SILENT = (!DEBUG EQ !FALSE), /INTERPOLATE) IF N_ELEMENTS(background) GT 1 THEN image = image - background ENDIF ENDIF ; Perform error checking : IF N_ELEMENTS(image) EQ 0 OR N_ELEMENTS(hdr) EQ 0 THEN $ MESSAGE, "Calibration could not be performed for : " + self._fileSpecification ; Update _calibrationModel property : self._calibrationArray = all[self._probe, self._instrument] self._CRPIX1 = hdr.CRPIX1 - 1 self._CRPIX2 = hdr.CRPIX2 - 1 self._CDELT1 = hdr.CDELT1 self._CDELT2 = hdr.CDELT2 self._CRVAL1 = hdr.CRVAL1 self._CRVAL2 = hdr.CRVAL2 ; convert self._CRVAL1/2 to degrees (FESTIVAL convention) ; convert self._CDELT1/2 to arcseonds (FESTIVAL convention) CASE hdr.CUNIT1 OF 'deg': self._CDELT1 = self._CDELT1*3600.0d 'arcsec': self._CRVAL1 = self._CRVAL1/3600.0d ELSE: ENDCASE CASE hdr.CUNIT2 OF 'deg': self._CDELT2 = self._CDELT2*3600.0d 'arcsec': self._CRVAL2 = self._CRVAL2/3600.0d ELSE: ENDCASE ; for HIs, fixes CRVAL1/2 if 0 in header based on nominal values IF self._Instrument EQ !HI1 OR self._Instrument EQ !HI2 THEN BEGIN IF (self._CRVAL1 EQ 0.0) AND (self._CRVAL2 EQ 0) THEN BEGIN IF self._probe EQ !STEREOA THEN BEGIN IF self._Instrument EQ !HI1 THEN dq = -13.98*!DDTOR $ ELSE dq = -53.68 * !DDTOR ENDIF ELSE BEGIN IF self._Instrument EQ !HI1 THEN dq = 13.98*!DDTOR $ ELSE dq = 53.68 * !DDTOR ENDELSE dk = hdr.CROTA*!DDTOR zp = COS(dq) xp = SIN(dq)*SIN(dk) yp = SIN(dq)*COS(dk) self._CRVAL2 = ASIN(xp)*!DRADEG self._CRVAL1 = ATAN(yp, zp)*!DRADEG ENDIF ENDIF ; Extract Geometry information from header self._HAEX = hdr.HAEX_OBS self._HAEY = hdr.HAEY_OBS self._HAEZ = hdr.HAEZ_OBS self._CarringtonLongitude = (hdr.CRLN_OBS + 360) MOD 360 self._CarringtonLatitude = hdr.CRLT_OBS self._SunDist = hdr.DSUN_OBS self._SunDistNormalization = 1.0d self._SolarNorthAngle = hdr.CROTA self._EclipticSolarNorthAngle = FESTIVAL_ECL_SOLAR_NORTH(self._HAEX, self._HAEY, self._HAEZ) BREAK END ; Undefined : ELSE: MESSAGE, "Unknown STEREO instruments" END BREAK END ELSE: MESSAGE, "Unknown probe" END ; Exclude !VALUES.F_NAN values : vec = WHERE(~FINITE(image), count) IF count GT 0 THEN BEGIN IF count EQ N_ELEMENTS(image) THEN $ MESSAGE, "Image could not be calibrated" image[vec] = 0 END ; Perform image rotation : ; Store image : IF PTR_VALID(self._pCalibratedImage) THEN $ *self._pCalibratedImage = TEMPORARY(FLOAT(image)) ELSE $ self._pCalibratedImage = PTR_NEW(FLOAT(image), /NO_COPY) ; Store FITS header : ; Change it eventually to structure : IF SIZE(hdr, /TYPE) NE 8 THEN $ hdr = FITSHead2Struct(hdr) IF PTR_VALID(self._pFITSHeader) THEN $ *self._pFITSHeader = TEMPORARY(hdr) ELSE $ self._pFITSHeader = PTR_NEW(hdr, /NO_COPY) ; Update size in memory : self->UPDATESIZEINMEMORY RETURN, out END ;+ ; NAME: ; FESTIVAL_DATA::FILTER ; ; PURPOSE: ; Perform filtering on an image using a user defined filtering sequence. ; ; INPUTS: ; oFestivalFilterGUI: an object reference to the FESTIVAL_FILTER_GUI wizard. ; ; KEYWORD PARAMETERS: ; None. ; ; OUTPUTS: ; 1 if filtering could be performed OK, 0 otherwise. ; ; MODIFICATION HISTORY: ; 29/08/06 - IAS ORSAY ;- FUNCTION FESTIVAL_DATA::FILTER, oFestivalFilterGUI ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL ; Reinitialize some object properties : IF PTR_VALID(self._pFilteredImage) THEN $ PTR_FREE, self._pFilteredImage IF PTR_VALID(self._pFilteringSequence) THEN $ PTR_FREE, self._pFilteringSequence ; Update size in memory : self->UPDATESIZEINMEMORY RETURN, !FALSE END IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> FILTER" ; Return value : out = !TRUE ; A scientific image must be available : IF ~PTR_VALID(self._pCalibratedImage) THEN $ MESSAGE, "No calibrated image available for : " + self._fileSpecification ; An invalid object was passed : IF ~OBJ_VALID(oFestivalFilterGUI) THEN $ MESSAGE, "An invalid FESTIVAL_FILTER_GUI object was passed" ; A wrong object was passed : IF ~OBJ_ISA(oFestivalFilterGUI, "FESTIVAL_FILTER_GUI") THEN $ MESSAGE, "An invalid FESTIVAL_FILTER_GUI object was passed" ; Get object properties : oFestivalFilterGUI->GETPROPERTY, ALL = all filterStruct = all[self._probe, self._instrument] ; Default is : _pFilteredImage = _pCalibratedImage IF PTR_VALID(self._pFilteredImage) THEN $ *self._pFilteredImage = *self._pCalibratedImage ELSE $ self._pFilteredImage = PTR_NEW(*self._pCalibratedImage) ; Filtering required : IF filterStruct._filterON THEN BEGIN ; Filtering sequence is valid : IF PTR_VALID(filterStruct._pFilteringSequence) THEN BEGIN ; Perform filtering filteringSequence = *filterStruct._pFilteringSequence ; Is a non-null filtering sequence available ? IF filteringSequence[0] NE '' THEN BEGIN ; Define initial image & header: image = *self._pCalibratedImage header = *self._pFITSHeader saved_header = header FOR i = 0, N_ELEMENTS(filteringSequence)-1 DO BEGIN filterSring = "image = " + filteringSequence[i] res = EXECUTE(filterSring) IF ~res THEN $ MESSAGE, filteringString + " failed for : " + self._fileSpecification header = saved_header ;prevents side effects if filter modifies header END ; Check filtered image validity : info = SIZE(image) IF info[0] EQ 0 THEN $ MESSAGE, "Filtered image is NOT a 2D array" ; Exclude !VALUES.F_NAN values : vec = WHERE(~FINITE(image), count) IF count GT 0 THEN BEGIN IF count EQ N_ELEMENTS(image) THEN $ MESSAGE, "Image could not be filtered" image[vec] = 0 END ; Store filtered image : IF PTR_VALID(self._pFilteredImage) THEN $ *self._pFilteredImage = TEMPORARY(FLOAT(image)) ELSE $ self._pFilteredImage = PTR_NEW(FLOAT(image), /NO_COPY) ; Update size in memory : self->UPDATESIZEINMEMORY ; Filtering is ON but empty filtering sequence : END ; Store filtering sequence : IF PTR_VALID(self._pFilteringSequence) THEN $ *self._pFilteringSequence = TEMPORARY(filteringSequence) ELSE $ self._pFilteringSequence = PTR_NEW(filteringSequence, /NO_COPY) END END ELSE $ IF !DEBUG EQ !TRUE THEN $ PRINT, "_pFilteredImage = _pCalibratedImage because no filtering sequence is available" RETURN, out END ;+ ; NAME: ; FESTIVAL_DATA::COMPUTEMINMAX ; ; PURPOSE: ; Compute min and max values of an image prior to enhancement. ; ; INPUTS: ; None ; ; KEYWORD PARAMETERS: ; MINI : Set this keyword to named variable that will contain the minimum image value. ; ; MAXI : Set this keyword to named variable that will contain the maximum image value. ; ; OUTPUTS: ; None ; ; MODIFICATION HISTORY: ; 04/09/06 - IAS ORSAY ;- PRO FESTIVAL_DATA::COMPUTEMINMAX, MINI = mini, MAXI = maxi ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL RETURN END IF ~PTR_VALID(self._pFilteredImage) THEN $ MESSAGE, "No valid filtered image available" sz = SIZE(*self._pFilteredImage) nx = 128>(sz[1]/8.0)<1024 ny = 128>(sz[2]/8.0)<1024 im = CONGRID(*self._pFilteredImage, nx, ny) x2 = ((FINDGEN(nx)/nx - 0.5)^2.0) # REPLICATE(1.0, ny) y2 = REPLICATE(1.0, nx) # ((FINDGEN(ny)/ny - 0.5)^2.0) r2 = x2 + y2 valid = WHERE((FINITE(im) EQ 1) AND (im NE !MISSING_VALUE) AND (r2 LT 0.25), count) IF count GT 0 THEN BEGIN im = im[valid] pos = WHERE(im GT 0, poscount) neg = WHERE(im LT 0, negcount) IF poscount GT 0 THEN im[pos] = SQRT(im[pos]) IF negcount GT 0 THEN im[neg] = -SQRT(-im[neg]) minval = 0.01 maxval = 0.99 minim = MIN(im, MAX = maxim) histo = HISTOGRAM(im, MIN = minim, MAX = maxim, NBINS=2000, LOCATIONS = x) histo = MEDIAN(histo, 3) tot = TOTAL(ABS(histo*x), /DOUBLE, /CUMULATIVE) tot = tot/tot[N_ELEMENTS(tot)-1] good = WHERE((tot GE minval) AND (tot LE maxval), count) IF count GT 0 THEN BEGIN mini = MIN(x[good], MAX = maxi) IF mini GT 0 THEN mini = mini^2.0 ELSE mini = -mini^2.0 IF maxi GT 0 THEN maxi = maxi^2.0 ELSE maxi = -maxi^2.0 ENDIF ELSE mini = MIN(im, MAX = maxi) IF mini EQ maxi THEN mini = MIN(im, MAX = maxi) ENDIF ELSE BEGIN maxi = 255.0 mini = 0.0 ENDELSE END PRO FESTIVAL_DATA::CHECK_MIN_MAX, enhancementAlgo, mini, maxi ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL END IF ~PTR_VALID(self._pFilteredImage) THEN $ MESSAGE, "No filtered image available" CASE enhancementAlgo OF !LOG: BEGIN pos = WHERE(*self._pFilteredImage GT 0, count) IF count GT 0 THEN minLogValue = MIN((*self._pFilteredImage)[pos],MAX=maxLogValue) $ ELSE BEGIN minLogValue = 1e-20 maxLogValue = 1e-20 END IF mini LE 0 THEN $ mini = minLogValue IF maxi LE 0 THEN $ maxi = maxLogValue END !SQUARE_ROOT: BEGIN IF mini LT 0.0 THEN $ mini = 0 IF maxi LT 0.0 THEN $ maxi = MAX(*self._pFilteredImage) > 0.0 END ELSE: ; Do nothing : END END ;+ ; NAME: ; FESTIVAL_DATA::ENAHNCE ; ; PURPOSE: ; Perform filtering on an image using a user defined filtering sequence. ; ; INPUTS: ; oFestivalFilterGUI: an object reference to the FESTIVAL_FILTER_GUI wizard. ; ; KEYWORD PARAMETERS: ; None. ; ; OUTPUTS: ; 1 if filtering could be performed OK, 0 otherwise. ; ; MODIFICATION HISTORY: ; 29/08/06 - IAS ORSAY ;- FUNCTION FESTIVAL_DATA::ENHANCE, oFestivalEnhancementGUI ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL ; Reinitialize some object properties : IF PTR_VALID(self._pEnhancedImage) THEN $ PTR_FREE, self._pEnhancedImage ; Reinitialize enhancement algorithm : self._enhancement = {FESTIVAL_ENHANCEMENT} ; Update size in memory : self->UPDATESIZEINMEMORY RETURN, !FALSE END IF !DEBUG EQ !TRUE THEN $ PRINT, "-------------------------------------------------------------------> ENHANCE" ; Check for input object validity : IF ~OBJ_VALID(oFestivalEnhancementGUI) THEN $ MESSAGE, "An invalid FESTIVAL_ENHANCEMENT_GUI object was passed" IF ~OBJ_ISA(oFestivalEnhancementGUI, "FESTIVAL_ENHANCEMENT_GUI") THEN $ MESSAGE, "An invalid FESTIVAL_ENHANCEMENT_GUI object was passed" ; A scientific image must be available : IF ~PTR_VALID(self._pFilteredImage) THEN $ MESSAGE, "No filtered image available for : " + self._fileSpecification ; Get all object properties : oFestivalEnhancementGUI->GETPROPERTY, ALL = all wavesList = *!WAVES_ARRAY[self._probe, self._instrument] filtersList = *!FILTERS_ARRAY[self._probe, self._instrument] IF N_ELEMENTS(wavesList) EQ 1 THEN $ ;Only one or only all wave = 0 $ ELSE BEGIN wave = WHERE(STRLOWCASE(wavesList) EQ STRLOWCASE(self._userWave), cwave) IF cwave EQ 0 THEN MESSAGE, "Image could not be enhanced" ENDELSE IF N_ELEMENTS(filtersList) EQ 1 THEN $ filter = 0 $ ELSE BEGIN filter = WHERE(STRLOWCASE(filtersList) EQ STRLOWCASE(self._userFilter), cfilter) IF cfilter EQ 0 THEN MESSAGE, "Image could not be enhanced" ENDELSE mode = ABS(self._deltaOfImageDiff) GT !epsilon ; Get target enhancement structure : enhanceStruct = all[self._probe, self._instrument, wave, filter, mode] ; Auto-scale is ON : IF enhanceStruct._autoScale THEN BEGIN self->COMPUTEMINMAX, MINI = mini, MAXI = maxi self->CHECK_MIN_MAX, enhanceStruct._algorithm, mini, maxi ; Update target structure : enhanceStruct._min = mini enhanceStruct._max = maxi ; Get target enhancement structure : all[self._probe, self._instrument, wave, filter, mode] = enhanceStruct oFestivalEnhancementGUI->SETPROPERTY, ALL = all END CASE enhanceStruct._algorithm OF !LINEAR: image = BYTSCL(*self._pFilteredImage, MIN = enhanceStruct._min, MAX = enhanceStruct._max) !SQUARE_ROOT: image = BYTSCL(SQRT(*self._pFilteredImage > enhanceStruct._min), MIN = SQRT(enhanceStruct._min), MAX = SQRT(enhanceStruct._max)) !LOG: image = BYTSCL(ALOG10(*self._pFilteredImage > enhanceStruct._min), MIN = ALOG10(enhanceStruct._min), MAX = ALOG10(enhanceStruct._max)) ELSE: MESSAGE, "Unknown enhancement algorithm" END ; Exclude !VALUES.F_NAN values : vec = WHERE(~FINITE(image), count) IF count GT 0 THEN BEGIN IF count EQ N_ELEMENTS(image) THEN $ MESSAGE, "Image could not be enhanced" image[vec] = 0 END ; Store enhanced image : IF PTR_VALID(self._pEnhancedImage) THEN $ *self._pEnhancedImage = TEMPORARY(image) ELSE $ self._pEnhancedImage = PTR_NEW(image, /NO_COPY) ; Update _enhancement object property : self._enhancement = enhanceStruct ; Update object size in memory : self->UPDATESIZEINMEMORY RETURN, !TRUE END PRO FESTIVAL_DATA::CLEANUP ; Free all pointers/objects : IF PTR_VALID(self._pFITSHeader) THEN $ PTR_FREE, self._pFITSHeader IF PTR_VALID(self._pCalibratedImage) THEN $ PTR_FREE, self._pCalibratedImage IF PTR_VALID(self._pFilteringSequence) THEN $ PTR_FREE, self._pFilteringSequence IF PTR_VALID(self._pFilteredImage) THEN $ PTR_FREE, self._pFilteredImage IF OBJ_VALID(self._oProjectedImage) THEN $ OBJ_DESTROY, self._oProjectedImage IF PTR_VALID(self._pContourOfNonMissing) THEN $ PTR_FREE, self._pContourOfNonMissing IF PTR_VALID(self._pProjectedUserDefinedMaskCoord) THEN $ PTR_FREE, self._pProjectedUserDefinedMaskCoord IF PTR_VALID(self._pEnhancedImage) THEN $ PTR_FREE, self._pEnhancedImage IF PTR_VALID(self._pProjCoord) THEN $ PTR_FREE, self._pProjCoord END ;+ ; NAME: ; FESTIVAL_DATA::INIT ; ; PURPOSE: ; Object constructor. ; ; INPUTS: ; None ; ; KEYWORD PARAMETERS: ; FESTIVAL_SEARCH_RESULT : A reference to a valid FESTIVAL_SEARCH_RESULT object. ; ; OUTPUTS: ; 0: Init OK. ; 1: Init Failed ; ; MODIFICATION HISTORY: ; 29/08/06 - IAS ORSAY ;- FUNCTION FESTIVAL_DATA::INIT, FESTIVAL_SEARCH_RESULT = oFestSearchResult, $ BATCH_MODE_IS_ON = BatchModeIsON, $ DATA_ENGINE = oDataEngine, $ _EXTRA = e ; Error handler : err = 0 CATCH, err IF err NE 0 THEN BEGIN ; Update FESTIVAL error log : FESTIVAL_UPDATEJOURNAL HELP, /MESSAGE, /LAST_MESSAGE IF !DEBUG EQ !TRUE THEN BEGIN PRINT, !error_state.msg END CATCH, /CANCEL RETURN, !FALSE END FESTIVAL_DATA_TYPES ; Return value : out = !TRUE IF OBJ_VALID(oDataEngine) THEN BEGIN IF ~OBJ_ISA(oDataEngine, "FESTIVAL_DATA_ENGINE") THEN $ MESSAGE, "An invalid FESTIVAL_DATA_ENGINE object was found" ELSE $ self._oDataEngine = oDataEngine END ELSE $ MESSAGE, "An invalid FESTIVAL_DATA_ENGINE object was found" ; First way of initialising a FESTIVAL_DATA object : IF N_ELEMENTS(oFestSearchResult) GT 0 THEN BEGIN ; It is an object : IF OBJ_VALID(oFestSearchResult) THEN BEGIN IF OBJ_VALID(oFestSearchResult) THEN BEGIN ; Defines some object properties : oFestSearchResult->GETPROPERTY, $ ; Returns image acquisition date : UTCDATE = utcdate, $ ; Returns probe name : F_PROBE = probe, $ ; Returns instrument name : F_INSTRUMENT = instrument, $ ; Returns file specification : FILESPECIFICATION = fileSpec, $ ; Returns fullfilepath FULLFILEPATH = fullFilepath, $ ; User wave : F_WAVE = wave, $ ; Filter : F_FILTER = filter, $ FITSFILENAME= fitsfilename, $ GETMETHOD = getmethod ; is it a stereo triplet ? IF (probe NE !SOHO) THEN BEGIN oFestSearchResult->GETPROPERTY, TRIPLET_REF = triplet_ref, POLAR=polar IF OBJ_VALID(triplet_ref[0]) THEN BEGIN ; this is a triplet triplet_ref[0]->getproperty, FULLFILEPATH = fullfilepath0,$ FITSFILE = fitsfilename0 triplet_ref[1]->getproperty, FULLFILEPATH = fullfilepath1, $ FITSFILE = fitsfilename1 triplet_ref[2]->getproperty, FULLFILEPATH = fullfilepath2, $ FITSFILE = fitsfilename2 self._fullFilePath = [ fullfilepath0, fullfilepath1, fullfilepath2 ] self._matchedPolarity = !TRUE case polar of 'TB':self._polarityType = !TB 'PB':self._polarityType = !PB 'Mu':self._polarityType = !MU '%' :self._polarityType = !PERCENT endcase END ELSE BEGIN self._matchedPolarity = !FALSE self._fullFilePath = fullFilePath END END ELSE BEGIN self._matchedPolarity = !FALSE self._fullFilePath = fullFilePath END IF (1 EQ 1) THEN BEGIN ; Store file specification : self._fileSpecification = fileSpec IF (getmethod EQ 'vso') THEN BEGIN show_progress = ~keyword_set(BatchModeIsON) VSO_DOWNLOAD_DIRECTORY = !FESTIVAL_SAVE_DIRECTORY+PATH_SEP()+'downloaded_data'+$ PATH_SEP() http = obj_new('http') IF (self._matchedPolarity EQ !TRUE) THEN BEGIN IF !DEBUG EQ !TRUE THEN BEGIN print, "Files will be put in "+VSO_DOWNLOAD_DIRECTORY print, "Downloading "+self._fullFilePath[0] ENDIF http->copy,fullfilepath0, OUT_DIR = VSO_DOWNLOAD_DIRECTORY, $ PROGRESS = show_progress self._fullFilePath[0] = VSO_DOWNLOAD_DIRECTORY+fitsfilename0 IF !DEBUG EQ !TRUE THEN BEGIN print, "Downloading "+self._fullFilePath[1] ENDIF http->copy,fullfilepath1, OUT_DIR = VSO_DOWNLOAD_DIRECTORY, $ PROGRESS = show_progress self._fullFilePath[1] = VSO_DOWNLOAD_DIRECTORY+fitsfilename1 IF !DEBUG EQ !TRUE THEN BEGIN print, "Downloading "+self._fullFilePath[2] ENDIF http->copy,fullfilepath2, OUT_DIR = VSO_DOWNLOAD_DIRECTORY, $ PROGRESS = show_progress self._fullFilePath[2] = VSO_DOWNLOAD_DIRECTORY+fitsfilename2 IF !DEBUG EQ !TRUE THEN BEGIN print, "Triplet downloaded" ENDIF END ELSE BEGIN IF !DEBUG EQ !TRUE THEN BEGIN print, "Files will be put in "+VSO_DOWNLOAD_DIRECTORY print, "Downloading "+self._fullFilePath[0] ENDIF http->copy,fullFilePath, OUT_DIR = VSO_DOWNLOAD_DIRECTORY, $ PROGRESS = show_progress self._fullFilePath = VSO_DOWNLOAD_DIRECTORY+fitsfilename IF !DEBUG EQ !TRUE THEN BEGIN print, "File downloaded" ENDIF END obj_destroy, http END ; Store UTC date : self._UTCDate = utcdate ; Store probe ID : self._probe = probe ; Store wave : self._userWave = wave ; Store filter : self._userFilter = filter ; Initialise coordinate system : SWITCH self._probe OF !SOHO: BEGIN IF ~PTR_VALID(self._pProjCoord) THEN $ self._pProjCoord = PTR_NEW({FESTIVAL_PROJCOORD}) (*self._pProjCoord)._coordSystem = !HELIOCENTRIC_SOLAR_NORTH_UP BREAK END !STEREOA: !STEREOB: BEGIN IF ~PTR_VALID(self._pProjCoord) THEN $ self._pProjCoord = PTR_NEW({FESTIVAL_PROJCOORD}) (*self._pProjCoord)._coordSystem = !HELIOCENTRIC_ECLIPTIC BREAK END ELSE: MESSAGE, "Unknown probe" END ; Store instrument ID : self._instrument = instrument ; Store corresponding FESTIVAL_SEARCH_RESULT object : self._oRefSearchResult = oFestSearchResult ; Initialise projection to "Mercator" : (*self._pProjCoord)._sMap.up_name = !PROJECTIONS[0] ; Default filtering sequence is an empty string : self._pFilteringSequence = PTR_NEW('') END ELSE $ out = !FALSE ; An invalid FESTIVAL_SEARCH_RESULT object was passed : END ELSE $ out = !FALSE ; An invalid FESTIVAL_SEARCH_RESULT object was passed : END ELSE $ out = !FALSE ; Second way of initialising a FESTIVAL_DATA object : ; This way allows to build a FESTIVAL_DATA difference object from 2 FESTIVAL_DATA objects : END ELSE IF N_ELEMENTS(e) GT 0 THEN BEGIN ; Check extra-parameters validity : ; Must contain 5 tags : IF N_TAGS(e) EQ 5 THEN BEGIN ; Get tag names : tagNames = TAG_NAMES(e) ; Check for tags availability : vec = WHERE(tagNames EQ 'FESTIVALDATA1', count0) vec = WHERE(tagNames EQ 'FESTIVALDATA2', count1) vec = WHERE(tagNames EQ 'FESTIVAL_FILTER_GUI', count2) vec = WHERE(tagNames EQ 'FESTIVAL_CALIBRATION_GUI', count3) vec = WHERE(tagNames EQ 'FESTIVAL_PROJCOORD_GUI', count4) ; All required keywords are present : IF count0 GT 0 AND count1 GT 0 AND count2 GT 0 AND count3 GT 0 AND count4 GT 0 THEN BEGIN ; Check for object validity : IF OBJ_VALID(e.festivalData1) AND OBJ_VALID(e.festivalData2) AND OBJ_VALID(e.festival_filter_gui) AND $ OBJ_VALID(e.festival_calibration_gui) AND OBJ_VALID(e.festival_projcoord_gui) THEN BEGIN ; Check for object classes : IF OBJ_ISA(e.festivalData1, "FESTIVAL_DATA") AND OBJ_ISA(e.festivalData2, "FESTIVAL_DATA") AND $ OBJ_ISA(e.festival_filter_gui, "FESTIVAL_FILTER_GUI") AND OBJ_ISA(e.festival_calibration_gui, "FESTIVAL_CALIBRATION_GUI") AND $ OBJ_ISA(e.festival_projcoord_gui, "FESTIVAL_PROJCOORD_GUI") THEN BEGIN ; Everything is fine, build difference object : out = self->MAKE_DIFF(e.festivalData1, e.festivalData2, $ e.festival_filter_gui, e.festival_calibration_gui, e.festival_projcoord_gui) END ELSE $ out = !FALSE END ELSE $ out = !FALSE END ELSE $ out = !FALSE END ELSE $ out = !FALSE END RETURN, out END ; Define object properties : PRO FESTIVAL_DATA__DEFINE tmp = {FESTIVAL_DATA, $ ; ******************** GENERAL OBJECT PROPERTIES ************************ ; Object file specifiation : _fileSpecification: '', $ _fullFilePath: STRARR(3), $ _matchedPolarity: !FALSE, $ ; UTC image acquisition date : _UTCDate: 0.0d, $ ; Probe identifier associated to taht image : _probe: 0, $ ; Instrument identifier associated to that image : _instrument: 0, $ ; Reference to the corresponding FESITVAL_SEARCH_RESULT object : _oRefSearchResult: OBJ_NEW(), $ ; Pointer to the FITS header structure associated to that image : _pFITSHeader: PTR_NEW(), $ ; Approximative memory used by that image : _sizeInMemory: 0L, $ ; Delay between the 2 images used for a difference image. ; 0.0 indicates that the filtered image does not contain a difference : _deltaOfImageDiff: 0.0, $ ; ********************************************************************** ; ********************** OBJECT CALIBRATION PROPERTIES ***************** ; Calibration model used for that image : _calibrationArray: {FESTIVAL_CALIBRATION}, $ ; Pointer to the 32 bits calibrated image. Temporary buffer not saved in ; history stack : _pCalibratedImage: PTR_NEW(), $ ; ********************************************************************** ; ********************** OBJECT FILTER PROPERTIES ********************** ; Pointer to the filtering sequence used for that image. ; Pointer to an empty string means no filtering sequence : _pFilteringSequence: PTR_NEW(), $ ; Pointer to the filtered image : _pFilteredImage: PTR_NEW(), $ ; ********************************************************************** ; ***************** OBJECT PROJECTION/COORDINATES PROPERTIES *********** ; Structure containing all information concerning the projection used to ; compute the projected image and mask (projection structure mask). ; TO BE MODIFIED. THIS STRUCTURE CONTAINS TOO MUCH INFORMATION : _pProjCoord: PTR_NEW(), $ ; 4 elements vector givng the projection limits lonMin, latMin, lonMax, latMax : _imageCoordinates: FLTARR(4), $ ; IDLGRIMAGE object created with the 8bit projected image : _oProjectedImage: OBJ_NEW(), $ ; UV coordinates of the 4 corners of the projected image : ; ; C0 = UVRange(*,0) = lower left corner ; C1 = UVRange(*,1) = lower right corner ; C2 = UVRange(*,2) = upper right corner ; C3 = UVRange(*,3) = upper right corner ; ; C3 ---- C2 ; | | ; | | ; C0 ---- C1 ; ; In general, it is not a rectangle (it depends on the projection used) _UVRange: FLTARR(2,4), $ ; Pointer to a byte array containing the contour of "good" values ; after a projection was performed. _pContourOfNonMissing: PTR_NEW(), $ ; Pointer to an array of coordinates of the projected mask defined by the user : _pProjectedUserDefinedMaskCoord: PTR_NEW(), $ ; FESTIVAL_MASKING structure associated to that image : _userMaskParameters: {FESTIVAL_MASKING}, $ ; ********************************************************************** ; ********************** OBJECT ENHANCEMENT PROPERTIES ***************** _enhancement: {FESTIVAL_ENHANCEMENT}, $ ; Pointer to the 8 bits enhances image. Temporary buffer not saved in ; history stack : _pEnhancedImage: PTR_NEW(), $ ; ********************************************************************** ; ************************* OBJECT GEOMETRY PRPERTIES ****************** _HAEX: 0.0d, $ ;X Ares Ecliptic (m) _HAEY: 0.0d, $ ;Y Ares Ecliptic (m) _HAEZ: 0.0d, $ ;Z Ares Ecliptic (m) _SunDist: 0.0d, $ ;Distance of the Sun (m) _SunDistNormalization: 1.0d, $ ;Distance normalization factor _CarringtonLongitude:0.0d, $ ;degrees _CarringtonLatitude:0.0d, $ ;degrees _SolarNorthAngle:0.0d, $ ;Angle between top of image and solar north (degrees) _EclipticSolarNorthAngle:0.0d, $ ;Angle between Ecliptic north and solar north (degrees) ; ********************************************************************** ; ************************* OBJECT ORDER PROPERTIES ******************** _displayOrder: 0, $ ; ********************************************************************** ; **************************** OTHER PROPERTIES ************************ _CRPIX1: 0.0d, $ _CRPIX2: 0.0d, $ _CDELT1: 0.0d, $ _CDELT2: 0.0d, $ _CRVAL1: 0.0d, $ _CRVAL2: 0.0d, $ _UVPerPixelResolution: DBLARR(2), $ _oVisuElt: OBJ_NEW(), $ _polarityType: 0, $ _userFilter: '', $ _userWave: '', $ ; Reference to the data engine object : _oDataEngine: OBJ_NEW()} END