;-------------------------------------------------------------------------------- ; ; Unit Name : l_Adj2SunOrEarth.pro ; ; Purpose : Set zero degrees spin angle to be the earth, sun, or moon. ; ; ; Development History: ; Author Date Build Description of Change ; -------------- --------- -------- ------------------------- ; ELH 11/00 v1.0 Original Implementation ; ELH 08/01 v1.0.7 Correct adjustment for ; short time periods where ; fill was used ; ELH 01/02 v1.0.8 Add new function, ; FindZeroDegBinNO ; ; ; File Revision Number: %I% ; File Last Modified : %E% %T% ; ;-------------------------------------------------------------------------------- ;------------------------------------------------------------------------------- ; Function: FindZeroDegBinNo ; Description: Find what bin number spin angle zero corresponds to. ; ; Return Value: type = integer ; Value Description ; ------------------------- ------------------------------ ; center_bin spin sector number corresponding to 0 degrees ; ; Argument List: ; Name Type Use Description ; ----------------- ------ --- --------------------------- ; max_spin_angle int I max spin angle value ; sectors int I spin sectors ; ; External Variables: ; Source Name Type Use Description ; --------------- --------- ---- ---- -------------------- ; ; Development History: ; Author Date Build Description of Change ; -------------- --------- -------- ------------------------- ; ELH 01/02 v1.0.8 Original implementation ;------------------------------------------------------------------------------- FUNCTION FindZeroDegBinNo, max_spin_angle, sectors zero_plot_bin_no = (max_spin_angle - 8.)/8. center_bin = fix (sectors - 1 - zero_plot_bin_no) RETURN, center_bin END ;-------------------------------------------------------------------------------- ; Function: MatchOA2Data ; Description: Sync the OA (sun pulse) to the correct data ; ; Return Value: type = long ; Value Description ; ------------------------- ------------------------------ ; sunp sun pulse sector ; ; Argument List: ; Name Type Use Description ; ----------------- ------ --- --------------------------- ; l_oa struct * I OA data fields ; sunp long I array of sun pulse sectors ; data_time double I time associated with data packets ; save_idx long I last index visited ; ; ; Development History: ; Author Date Build Description of Change ; -------------- --------- -------- ------------------------- ; ELH 11/00 v1.0 Original Implementation ; ELH 08/01 v1.0.7 . modified prev_ii index ; to check if zero ; . added "if done" code to ; interpolate a sun pulse if ; no sun pulse is available ; ;-------------------------------------------------------------------------------- FUNCTION MatchOA2Data, l_oa, sunp, data_time, save_idx n_sunp = n_elements (sunp) done = 0L ;-------------------------------------------------- ; sync the data to the OA data ;-------------------------------------------------- for ii = save_idx, n_sunp - 1L do begin next_ii = ii + 1L if (ii ne 0) then begin prev_ii = ii - 1L endif if (ii ge n_sunp-1L) then begin next_ii = ii endif else begin if (ii eq 0L) then begin prev_ii = ii endif endelse prev_st_tme = l_GetTime((*l_oa.startUdfTimePtr)[prev_ii], $ doy, hr,min,sec) next_st_tme = l_GetTime((*l_oa.startUdfTimePtr)[next_ii], $ doy, hr,min,sec) start_tme = l_GetTime((*l_oa.startUdfTimePtr)[ii], doy, hr,min,sec) stop_tme = l_GetTime((*l_oa.stopUdfTimePtr)[ii], doy, hr,min,sec) prev_sunp = sunp[prev_ii] next_sunp = sunp[next_ii] ;-------------------------------------------------- ; interpolate the sunp if the time difference ; between the next oa time and the current oa time ; is greater than a spins worth, but not greater ; than 5 minutes ;-------------------------------------------------- diff = next_st_tme - start_tme if (diff gt 125L) AND (diff lt 300L) then begin eSunp= l_Interpolate (prev_st_tme, start_tme, next_st_tme, $ prev_sunp, next_sunp) save_idx = ii return, eSunp endif else begin ;-------------------------------------------------- ; no need to interpolate, match data to sun pulse ; return sun pulse sector ;-------------------------------------------------- if (data_time ge start_tme) AND $ (data_time lt stop_tme) then begin save_idx = ii RETURN, sunp[ii] endif endelse done = 1L endfor ;--- endfor ii --- ;-------------------------------------------------- ; no matches, usually first/last spin, interpolate ;-------------------------------------------------- if (done) then begin if (save_idx eq n_sunp - 1L) then begin return, sunp[save_idx] endif else begin prev_st_tme = l_GetTime((*l_oa.startUdfTimePtr)[save_idx], $ doy, hr,min,sec) next_st_tme = l_GetTime((*l_oa.startUdfTimePtr)[save_idx+1L], $ doy, hr,min,sec) start_tme = l_GetTime((*l_oa.startUdfTimePtr)[save_idx], doy, hr,min,sec) stop_tme = l_GetTime((*l_oa.stopUdfTimePtr)[save_idx], doy, hr,min,sec) prev_sunp = sunp[save_idx] next_sunp = sunp[save_idx+1L] eSunp= l_Interpolate (prev_st_tme, start_tme, next_st_tme, $ prev_sunp, next_sunp) return, eSunp endelse endif END ;----------------------------------------------------------------- ; Procedure : l_Adj2SunOrEarth ; Description : Adjust the sun or earth sector to be at zero ; degree spin angle ; ; Return Value: type = ; Value Description ; ------------------------- ------------------------------ ; None ; ; Argument List: ; Name Type Use Description ; ----------------- ------ --- --------------------------- ; theCenter long I sector(s) at zero degrees ; orig_arr long I array of data ; dataTimes double I array of data times ; oarr long O array with sectors adjusted ; sector_format long I indicates if array is of a ; single scalar value or of ; 45 spin sectors ; EarthOrSun long I flag indicating adjusting data ; for earth, sun, or moon ; l_oa struct * I pointer to OA data fields ; ; ; External Variables: ; Source Name Type Use Description ; --------------- --------- ---- ---- -------------------- ; l_LenaPlot.pro MAX_PLOTS int G max plots per page ; MAX_WEB_SPINS int G max # spins accessed when ; using web interface ; NO_CNTS double G indicator of no counts ; NO_DATA double G indicator of no data ; ; ; ; Development History: ; Author Date Build Description of Change ; -------------- --------- -------- ------------------------- ; ELH 08/00 original implementation ; ELH 07/05/01 v1.0 changed spin loop to begin w/0 ; ELH 08/01 v1.0.7 . handle already filled data in ; event data packets ; . handle missing first/last spin ; ; ; ; NOTES: ; ; Earth center is always at sector ~17 ; Sun center is variable. For the sun the algorithm is ; the same as for the earth except that each pixel is ; replicated by 8, so instead of working with 0-44 spin ; sectors, we will have 0-364 sectors to work with ; ; Algorithm: ; Example: earth centered at zero degree spin angle ; ; input array output array ; index index ; 44 5 ----- ; 43 4 | ; 42 3 | use next spin's ; 41 2 | spin sectors 0-5 data ; 40 1 | ; 39 0 ----- ; 38 44 ; 37 43 ; : : ; : : ; 11 17 -----> spin angle 0, earth ; 10 16 ; : : ; : : ; 0 6 ; ; *** AS AN EXAMPLE, let's say that the earth's center is ; at spin sector 1 *** ; input array output array ; index index ; 44 34 ; 43 33 ; 42 32 ; 41 31 ; : : ; : : ; 11 1 -----> spin angle 0, earth ; 10 0 ; 9 44 ----- ; 8 43 | use previous spin's ; : : | spin sectors 35-44 & 0 data ; : : | ; 0 35 ----- ; ; ; ;----------------------------------------------------------------- PRO l_Adj2SunOrEarth, theCenter, orig_iarr, dataTimes, $ oarr, sector_format, EarthOrSun , l_oa, more_iarr_data , spin_ang_zero_bin COMMON PLOTDEFS, MAX_PLOTS, MAX_WEB_SPINS, NO_CNTS, NO_DATA nspins = n_elements (orig_iarr)/ sector_format zero_deg_bin = spin_ang_zero_bin ;--------------------------------------------------- ; if zero degress spin angle is the Sun then ; replicate each pixel by 8 ;--------------------------------------------------- if ((EarthOrSun eq 'E') OR (EarthOrSun eq 'N')) then begin ;------------------------------------ ; earth sectors ; center sector = 11 ;------------------------------------ center = float(zero_deg_bin) top_min = 0L top_max = center - 1 ;index 10 bot_min = center + 1 ;index 12 bot_max = sector_format - 1 ;44 elements iarr = orig_iarr spin_sectors = sector_format endif else begin ;------------------------------------ ; sun sectors ; center sector = 88 ;------------------------------------ ndegrees = sector_format * 8 center = float(zero_deg_bin * 8) top_min = 0L top_max = center - 1 ; index 87 bot_min = center + 1 ; index 89 bot_max = ndegrees - 1 ; 359 elements new_arr = fltarr (ndegrees, nspins) new_extra = fltarr (ndegrees, 2) for i = 0L, 1L do begin degree = 0L for j = 0L, sector_format - 1L do begin for d = 0L, 7L do begin new_extra[degree,i] = more_iarr_data[j,i] degree = degree + 1L endfor endfor endfor more_iarr_data = new_extra degree = 0L for i = 0L, nspins - 1L do begin degree = 0L for j = 0L, sector_format-1L do begin for d = 0L, 7L do begin new_arr[degree, i] = orig_iarr[j,i] degree = degree + 1L endfor endfor endfor iarr = new_arr spin_sectors = ndegrees endelse oarr = fltarr(spin_sectors, nspins) sectors = spin_sectors - 1L ;--------------------------------------------------------------------- ; in certain cases, as in the event data, the data will already ; contain "filled" data for data gaps when the data is synced. As a ; result, we don't want to include this fill data when we adjust. ; Therefore, the fill data is removed from the input array and an ; array of flag is used to indicated which spins contained fill. ;--------------------------------------------------------------------- fill_spins = intarr(nspins) orig_nspins = nspins if (sector_format eq 45L) then begin indx = where (iarr eq NO_DATA, NO_DATA_CNT) if (NO_DATA_CNT ge sectors) then begin tmp = iarr new_spin = 0L for spin = 0L, nspins - 1L do begin no_data_indx = where (iarr[*,spin] eq NO_DATA, ndcnt) if (ndcnt gt 0) then begin fill_spins[spin] = 1L endif else begin tmp[*, new_spin] = iarr[*,spin] new_spin = new_spin + 1L endelse endfor if (new_spin gt 0) then begin iarr = tmp[*,0:new_spin-1] nspins = new_spin endif endif endif ;--------------------------------------------------------------------- ; do the adjusting of data ;--------------------------------------------------------------------- idx = 0L stop_idx = 0L prev_center_sector = 0L center_sector = 0L for spin = 0L, nspins-1L do begin if ((EarthOrSun eq 'S') OR (EarthOrSun eq 'M')) then begin ;------------------------------- ; the sun sector is variable ;------------------------------- center_sector = MatchOA2Data (l_oa, theCenter, $ dataTimes[stop_idx], idx) stop_idx = stop_idx + sector_format endif else begin ;------------------------------- ; the earth sector is always at ; sector 17 ;------------------------------- center_sector = theCenter endelse ;--------------------------------------------------- ; sun or earth sector is already in the center ; just copy input array to output ;--------------------------------------------------- if (center_sector eq center) then begin oarr[*,spin] = iarr[*,spin] endif else begin ;--------------------------------------------------- ; move SE center to zero degree center ;--------------------------------------------------- oarr[center, spin] = iarr[center_sector, spin] ;--------------------------------------------------- ; if SE center is less than zero degree center ;--------------------------------------------------- if (center_sector ge top_min) and $ (center_sector le top_max) then begin ;--------------------------------------------------- ; determine indexes of the input array necessary ; to do the, these ; are the values that are greater than zero degrees ; center ;--------------------------------------------------- bot_beg = center_sector + 1 bot_diff= sectors - center - 1 bot_end = center_sector + bot_diff + 1 oarr[center+1:spin_sectors-1, spin] = iarr[bot_beg:bot_end,spin] ;--------------------------------------------------- ; determine indexes of the input array , these ; are the values that are less than zero degrees ; center ;--------------------------------------------------- top_beg = bot_end + 1 top_end = spin_sectors - 1 diff = top_end - top_beg + 1 remaining = center - diff if (remaining gt 0L) then begin oarr[diff:center-1, spin] = iarr[0:remaining-1, spin] endif ;--------------------------------------------------- ; need to use previous spins data to fill ;--------------------------------------------------- if (diff gt 0L) then begin if (spin ne 0L) then begin oarr[0:diff-1, spin] = iarr[top_beg:top_end, spin-1L] endif else begin oarr[0:diff-1, spin] = more_iarr_data[top_beg:top_end, 0] endelse endif endif else begin ;--------------------------------------------------- ; if SE center is greater than zero degree center ;--------------------------------------------------- if (center_sector ge bot_min) and $ (center_sector le bot_max) then begin top_beg = center_sector - center top_end = center_sector - 1 oarr[0:center-1,spin] = iarr[top_beg:top_end,spin] bot_beg = center_sector + 1 bot_end = spin_sectors - 1 diff = bot_end - bot_beg + 1 if (center_sector eq spin_sectors -1) then begin bot_beg = 0L bot_end = (spin_sectors - 1) - (center + 1) diff = bot_end - bot_beg + 1 endif oarr[center+1:center+diff,spin] = iarr[bot_beg:bot_end,spin] ;--------------------------------------------------- ; if last spin fill with no data else use next ; spins data ;--------------------------------------------------- remaining = (sectors - (center+diff+1)) + 1 if (remaining gt 0L) then begin if (spin eq nspins-1L) then begin oarr[center+diff+1:spin_sectors-1,spin] = $ more_iarr_data[0:remaining-1, 1] endif else begin oarr[center+diff+1:spin_sectors-1,spin] = $ iarr[0:remaining-1, spin+1L] endelse endif endif endelse endelse endfor ;--------------------------------------------------------------------- ; put the fill back into the output array in original location ;--------------------------------------------------------------------- new_spin = 0L if (sector_format eq 45L) then begin if (NO_DATA_CNT gt 0) then begin tmp = oarr for spin = 0L, orig_nspins - 1L do begin if (fill_spins[spin] eq 1L) then begin tmp [*, spin] = NO_DATA endif else begin tmp[*,spin] = oarr[*,new_spin] new_spin = new_spin + 1L endelse endfor oarr = tmp endif endif RETURN END