;+ ; NAME: ; vu_new_time ; PURPOSE: ; Create or update averaged tomography files from original 'raw' files ; CATEGORY: ; Tomography: I/O ; CALLING SEQUENCE: PRO vu_new_time, ut, path=path, filter=filter, destination=destination, $ ff=ff, update=update, triangle=triangle, nofuture=nofuture, setbad=setbad,$ count=count, silent=silent, rounds=rounds, gzip=gzip ; INPUTS: ; ut array[*]; type: time structure ; /update NOT set: times for which new averaged files are ; to be calculated; should be in chronological order. ; if /update set: only ut[0] is used and usually refers to ; the time of the last tomography run (i.e. the time of ; the last 'raw' file available. All files in 'destination' ; which are affected by this raw file are updated. ; OPTIONAL INPUT PARAMETERS: ; path=path scalar; type: string ; directory where to search for 'raw' files to be used ; to calculate the new averaged file ; (passed to vu_select) ; filter=filter scalar; type: string ; file name filter for 'raw' files (incl. wildcard) ; (passed to vu_select) ; destination=destination ; scalar; type string ; destination directory of the new averaged file ; if not specified, then no output file is written. ; update_fast=update_fast ; if set then files in 'destination' are updated ; ; triangle=triangle ; array[4]; type: float; default: [ [4,-(7+4),7-4]/!sun.synodicp, 1.0 ] ; defines the range of time which affects the averaging ; near a given time, i.e. files with times inside this range ; will be given a non-zero weight in the averaging process. ; (see href=vu_weight=). ; /nofuture if set, the average is calculated from files with times earlier than ; the specified time. ; /setbad passed to href=vu_weight= ; /silent suppresses messages from vu_read and vu_write ; OUTPUTS: ; ff ; OPTIONAL OUTPUT PARAMETERS: ; count=count scalar; type: integer ; if /update NOT set: # times in 'ut' for which new averaged files ; were created ; if /update set: # times around ut[0] for which averaged files ; were found and updated. ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; InitVar, Carrington, vu_select, vu_new_time ; vu_write, where_common, TimeGet, vu_weight, vu_mean, IsType ; TimeUnit, TimeOp, IsBadTime, vu_get, vu_set ; PROCEDURE: ; > vu_select is called with keyword /nohdr set, i.e. file names ; are returned without actually reading the headers. ; MODIFICATION HISTORY: ; MAR-2001, Paul Hick (UCSD/CASS) ; AUG-2002, Paul Hick (UCSD/CASS) ; Added /allow_nrad_changes to vu_select call ; NOV-2003, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Added /gzip keyword ;- InitVar, update , /key InitVar, nofuture, /key InitVar, triangle, [ 4,-(7+4),7-4, 1.0 ] IF update AND IsType(destination, /undefined) THEN $ message, 'keyword /update is set, but no directory is specified to look for files to be updated' utt = Carrington(ut,/get_time) uday = TimeUnit(/day) IF update THEN BEGIN message, /info, 'updating ...' ; Get range of times affected by the new tomography files for time utt range = TimeOp(/add, utt[0],TimeSet(/diff, day=-triangle[0]-triangle[[2,1]])) ; Get a list of files from the destination directory. Don't read the ; headers yet. Just extract the Carrington variables from the file names all_rots = vu_select(files, /nohdr, path=destination, filter=filter, count=count) IF count NE 0 THEN BEGIN ; Select the files inside time range 'range'. For these files we ; read the headers. tmp = where( TimeOp(/subtract,all_rots,range[0],uday) GE 0 AND TimeOp(/subtract,all_rots,range[1],uday) LE 0, count) IF count NE 0 THEN BEGIN files = files[tmp] hdr = vu_select(files, /check, /allow_nrad_changes, rots=rots, count=count) ; Safety belt (should be removed at some point) IF (where(TimeOp(/subtract,vu_get(hdr,/uttime),rots,uday) NE 0))[0] NE -1 THEN $ message, /info, 'should not have happened' vu_new_time, vu_get(hdr,/uttime), path=path, filter=filter, destination=destination, $ setbad=setbad, silent=silent, gzip=gzip ENDIF ENDIF message, /info, 'at time '+TimeGet(utt[0],/ymd)+':'+strcompress(count)+' files updated' ENDIF ELSE BEGIN weight_range = triangle[0]+triangle[1:2] ; Get a list of all raw files to be used to calculate the averages. ; Don't read the headers yet. Just extract the times from the file names. ; We use these to determine which files we need to read. all_rots = vu_select(all_files, /nohdr, path=path, filter=filter, count=cnt, rounds=rounds) ; Loop over all times for which averaged files are needed count = 0 nut = n_elements(utt) old_rots = IsBadTime(/get) FOR i=0,nut-1 DO BEGIN tmp = TimeOp(/add,utt[i],TimeSet(/diff,day=weight_range)) ; Range of times around utt[i] with non-zero weights ; Find the files around utt[i], that will have a non-zero weight. ; If /nofuture is set only look for files with times earlier than utt[i] CASE nofuture OF 0: tmp = where( TimeOp(/subtract,all_rots,tmp[0],uday) GE 0 AND TimeOp(/subtract,all_rots,tmp[1],uday) LE 0, cnt ) 1: tmp = where( TimeOp(/subtract,all_rots,tmp[0],uday) GE 0 AND TimeOp(/subtract,all_rots,utt[i],uday) LE 0, cnt ) ENDCASE IF cnt EQ 0 THEN BEGIN message, /info, 'no raw files available near '+ $ TimeGet(utt[i], /ymd)+' ('+string(Carrington(utt[i]),format='(F9.4)')+')' ENDIF ELSE BEGIN files = all_files[tmp] ; Files needed for time utt[i] rots = all_rots [tmp] ; Compare current list of files 'rots' with the list 'old_rots' ; from the previous pass through the loop. there = where_common(TimeOp(/subtract,rots,rots[0],uday), TimeOp(/subtract,old_rots,rots[0],uday), $ absent=absent, inref=inref, count=nthere) all = absent[0] EQ -1 AND nthere EQ n_elements(old_rots) AND (where(there NE inref))[0] EQ -1 IF all THEN BEGIN ; message, /info, 'no new files needed' ENDIF ELSE IF nthere EQ 0 THEN BEGIN ; No data available yet ; If no files read (nthere=0) then read the whole 'files' list hdr = vu_select(files, /check, /allow_nrad_changes, count=cnt, /read, /get_full, ff=ff, silent=silent, rounds=rounds) ENDIF ELSE BEGIN ; Some data available already hdr = hdr[ inref] ; Pick up data already read ff = ff [*,*,*,*,inref] IF absent[0] EQ -1 THEN BEGIN ; No missing data files = files[there] rots = rots [there] ENDIF ELSE BEGIN ; Read absent data ; Read the absent files (if any) into the add_rots, add_hdr, and add_ff arrays add_files = files[absent] add_hdr = vu_select(add_files, /check, /allow_nrad_changes, rots=add_rots, count=add_cnt, /read, /get_full, ff=add_ff, silent=silent) IF add_cnt EQ 0 THEN message, 'oops, should not have happened' ; Bit of a kludge here. Since the /allow_nrad_changes ; keyword is used in vu_select above, there is no guarantee ; that nRad is the same as for the data already available. ; Compare nRad values here, and adjust to the lowest of the ; two. This is irreversible: nRad can get smaller, but never ; can get bigger again. nrad = vu_get( hdr[0], /nrad) add_nrad = vu_get(add_hdr[0], /nrad) IF nrad GT add_nrad THEN BEGIN ; Truncate data already available to add_nrad message, /info, 'truncating existing data' ff = ff[*,*,0:add_nrad-1,*,*] hdr = vu_set(hdr, nrad=add_nrad) ENDIF ELSE IF nrad LT add_nrad THEN BEGIN ; Truncate new data to nrad message, /info, 'truncating new data' add_ff = add_ff[*,*,0:nrad-1,*,*] hdr = vu_set(hdr,nrad=nrad) ENDIF cnt = nthere+add_cnt files = [files[there], add_files] rots = [rots [there], add_rots ] hdr = [hdr, add_hdr] sz = size(ff, /dim) ff = reform( ff, n_elements( ff), /overwrite) add_ff = reform(add_ff, n_elements(add_ff), /overwrite) ff = [ff, add_ff] ff = reform(ff, [sz[0:3],cnt], /overwrite) ENDELSE ENDELSE IF cnt EQ 0 THEN BEGIN message, /info, 'no files processed at '+TimeGet(utt[i], /ymd)+ $ string(Carrington(utt[i]),format='(F9.4)') delvar, old_rots ENDIF ELSE BEGIN ww = vu_weight(utt[i], vu_get(hdr, /uttime), triangle=triangle) hdr_mean = vu_mean(hdr, ff, ww, tt_weight=utt[i], userinfo=userinfo, ff_mean=ff_mean, setbad=setbad) count = count+1 vu_write, hdr_mean, ff_mean, userinfo=userinfo, destination=destination, silent=silent, gzip=gzip old_rots = rots ENDELSE ENDELSE ENDFOR IF nut GT 1 THEN message, /info, $ 'files created for'+strcompress(count)+'/'+strcompress(nut,/rem)+' times' ENDELSE RETURN & END