FUNCTION ADD_DETAIL, DEF, ERRMSG=ERRMSG,NOCHECK_DB=NOCHECK_DB ON_ERROR, 2 ; ; Initialize RESULT to represent non-success. If the routine is successful, ; this value will be updated below. ; RESULT = 0 ; ; Check the input parameters ; IF N_PARAMS() NE 1 THEN BEGIN MESSAGE = 'Syntax: Result = ADD_DETAIL(DEF)' GOTO, HANDLE_ERROR ENDIF ; ; Make sure that the user has privilege to write into the database. ; IF !PRIV LT 2 THEN BEGIN MESSAGE = '!PRIV must be 2 or greater to write into the database' GOTO, HANDLE_ERROR ENDIF ; ; Check each of the structure components to verify that it is of the correct ; type and size. ; DEF0 = DEF(0) ; IF DATATYPE(DEF0.PROG_ID,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag PROG_ID must be a short integer' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.PROG_ID) NE 1 THEN BEGIN MESSAGE = 'Tag PROG_ID must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.STUDY_ID,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag STUDY_ID must be a short integer' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.STUDY_ID) NE 1 THEN BEGIN MESSAGE = 'Tag STUDY_ID must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.STUDYVAR,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag STUDYVAR must be a short integer' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.STUDYVAR) NE 1 THEN BEGIN MESSAGE = 'Tag STUDYVAR must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.SCI_OBJ,1) NE 'String' THEN BEGIN MESSAGE = 'Tag SCI_OBJ must be a character string' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.SCI_OBJ) NE 1 THEN BEGIN MESSAGE = 'Tag SCI_OBJ must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MAX(STRLEN(DEF.SCI_OBJ)) GT 50 THEN BEGIN $ MESSAGE = 'Tag SCI_OBJ must be 50 characters or less' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.SCI_SPEC,1) NE 'String' THEN BEGIN MESSAGE = 'Tag SCI_SPEC must be a character string' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.SCI_SPEC) NE 1 THEN BEGIN MESSAGE = 'Tag SCI_SPEC must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MAX(STRLEN(DEF.SCI_SPEC)) GT 50 THEN BEGIN MESSAGE = 'Tag SCI_SPEC must be 50 characters or less' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.CMP_NO,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag CMP_NO must be a short integer' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.CMP_NO) NE 1 THEN BEGIN MESSAGE = 'Tag CMP_NO must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.OBJECT,1) NE 'String' THEN BEGIN MESSAGE = 'Tag OBJECT must be a character string' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.OBJECT) NE 1 THEN BEGIN MESSAGE = 'Tag OBJECT must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MAX(STRLEN(DEF.OBJECT)) GT 3 THEN BEGIN MESSAGE = 'Tag OBJECT must be 3 characters or less' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.OBJ_ID,1) NE 'String' THEN BEGIN MESSAGE = 'Tag OBJ_ID must be a character string' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.OBJ_ID) NE 1 THEN BEGIN MESSAGE = 'Tag OBJ_ID must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MAX(STRLEN(DEF.OBJ_ID)) GT 6 THEN BEGIN MESSAGE = 'Tag OBJ_ID must be 6 characters or less' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.DATE_OBS,1) NE 'Double' THEN BEGIN MESSAGE = 'Tag DATE_OBS must be a double precision number' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.DATE_OBS) NE 1 THEN BEGIN MESSAGE = 'Tag DATE_OBS must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.DATE_END,1) NE 'Double' THEN BEGIN MESSAGE = 'Tag DATE_END must be a double precision number' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.DATE_END) NE 1 THEN BEGIN MESSAGE = 'Tag DATE_END must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.ORIG_DUR,1) NE 'Double' THEN BEGIN MESSAGE = 'Tag ORIG_DUR must be a double precision number' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.ORIG_DUR) NE 1 THEN BEGIN MESSAGE = 'Tag ORIG_DUR must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.N_RASTERS1,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag N_RASTERS1 must be a short integer' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.N_RASTERS1) NE 1 THEN BEGIN MESSAGE = 'Tag N_RASTERS1 must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.TIME_TAGGED,1) NE 'Byte' THEN BEGIN MESSAGE = 'Tag TIME_TAGGED must be a byte value' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.TIME_TAGGED) NE 1 THEN BEGIN MESSAGE = 'Tag TIME_TAGGED must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MAX(DEF.TIME_TAGGED) GT 1 THEN BEGIN MESSAGE = 'Tag TIME_TAGGED must be either 0 or 1' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.TRACKING,1) NE 'Byte' THEN BEGIN MESSAGE = 'Tag TRACKING must be a byte value' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.TRACKING) NE 1 THEN BEGIN MESSAGE = 'Tag TRACKING must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MAX(DEF.TRACKING) GT 1 THEN BEGIN MESSAGE = 'Tag TRACKING must be either 0 or 1' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.N_POINTINGS,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag N_POINTINGS must be a short integer value' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.N_POINTINGS) NE 1 THEN BEGIN MESSAGE = 'Tag N_POINTINGS must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MIN(DEF.N_POINTINGS) LT 0 THEN BEGIN MESSAGE = 'Tag N_POINTINGS must not be negative' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.N_REPEAT_S,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag N_REPEAT_S must be a short integer value' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.N_REPEAT_S) NE 1 THEN BEGIN MESSAGE = 'Tag N_REPEAT_S must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MIN(DEF.N_REPEAT_S) LE 0 THEN BEGIN MESSAGE = 'Tag N_REPEAT_S must be positive' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.FLAG_MASTER,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag FLAG_MASTER must be a short integer value' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.FLAG_MASTER) NE 1 THEN BEGIN MESSAGE = 'Tag FLAG_MASTER must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.GSET_ID,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag GSET_ID must be a short integer value' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.GSET_ID) NE 1 THEN BEGIN MESSAGE = 'Tag GSET_ID must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(DEF0.GET_RAW,1) NE 'Byte' THEN BEGIN MESSAGE = 'Tag GET_RAW must be a byte value' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.GET_RAW) NE 1 THEN BEGIN MESSAGE = 'Tag GET_RAW must be a scalar' GOTO, HANDLE_ERROR END ELSE IF MAX(DEF.GET_RAW) GT 1 THEN BEGIN MESSAGE = 'Tag GET_RAW must be either 0 or 1' GOTO, HANDLE_ERROR ENDIF ; ; See if the PROG_NUM parameter exists. If it doesn't then use 0. ; IF TAG_EXIST(DEF0, 'PROG_NUM') THEN BEGIN IF DATATYPE(DEF0.PROG_NUM,1) NE 'Long' THEN BEGIN MESSAGE = 'Tag PROG_NUM must be a long integer' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(DEF0.PROG_NUM) NE 1 THEN BEGIN MESSAGE = 'Tag PROG_NUM must be a scalar' GOTO, HANDLE_ERROR ENDIF PROG_NUM = DEF.PROG_NUM END ELSE PROG_NUM = REPLICATE(0L, N_ELEMENTS(DEF)) ; ; Extract the first instance of the structure in the POINTINGS tag, and check ; it's tags. ; TEST = (DEF0.POINTINGS)(0) ; IF DATATYPE(TEST.INS_X,1) NE 'Float' THEN BEGIN MESSAGE = 'Tag INS_X must be a floating point number' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(TEST.INS_X) NE 1 THEN BEGIN MESSAGE = 'Tag INS_X must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(TEST.INS_Y,1) NE 'Float' THEN BEGIN MESSAGE = 'Tag INS_Y must be a floating point number' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(TEST.INS_Y) NE 1 THEN BEGIN MESSAGE = 'Tag INS_Y must be a scalar' GOTO, HANDLE_ERROR ENDIF ; IF DATATYPE(TEST.ZONE_ID,1) NE 'Integer' THEN BEGIN MESSAGE = 'Tag ZONE_ID must be a short integer' GOTO, HANDLE_ERROR END ELSE IF N_ELEMENTS(TEST.ZONE_ID) NE 1 THEN BEGIN MESSAGE = 'Tag ZONE_ID must be a scalar' GOTO, HANDLE_ERROR ENDIF ; ; The number of pointings supplied must match the number specified. ; IF MAX(DEF.N_POINTINGS) GT N_ELEMENTS(DEF0.POINTINGS) THEN BEGIN MESSAGE = 'Number of pointings does not match array size' GOTO, HANDLE_ERROR ENDIF ; ; Make sure that the program ID matches an entry in the CDS program database. ; CHECK_DB=1-KEYWORD_SET(NOCHECK_DB) FOR I = 0, N_ELEMENTS(DEF)-1 DO BEGIN IF CHECK_DB THEN BEGIN IF DEF(I).PROG_ID NE 0 THEN BEGIN GET_PROGRAM, DEF(I).PROG_ID, TEMP IF TEMP.PROG_ID LE 0 THEN BEGIN MESSAGE = 'Program ID ' + STRTRIM(DEF(I).PROG_ID,2) + $ ' not found in database' GOTO, HANDLE_ERROR ENDIF ENDIF ; ; Make sure that the campaign number matches an entry in the SOHO campaign ; database. ; IF DEF(I).CMP_NO NE 0 THEN BEGIN GET_CAMPAIGN, DEF(I).CMP_NO, TEMP IF (TEMP.CMP_NO LE 0) AND (DEF(I).CMP_NO NE 1) THEN BEGIN MESSAGE = 'Warning - Campaign number ' + STRTRIM(DEF(I).CMP_NO,2) + $ ' not found in database' MESSAGE,MESSAGE,/CONT ; IF (DEF(I).CMP_NO LT 0) THEN GOTO, HANDLE_ERROR ENDIF ENDIF ; Make sure that the study ID and study variation index match an entry in the ; CDS study database. ; GET_STUDY, DEF(I).STUDY_ID, DEF(I).STUDYVAR, TEMP IF TEMP.STUDY_ID LE -1 THEN BEGIN MESSAGE = 'Study ID/variation ' + TRIM(DEF(I).STUDY_ID) + $ ',' + TRIM(DEF(I).STUDYVAR) + ' not found in database' GOTO, HANDLE_ERROR ENDIF ; ; If any of the rasters use the GIS detector, then make sure that GSET_ID is ; valid. ; IF TEMP.N_RASTER_DEF GT 0 THEN BEGIN USE_GIS = 0 FOR IR = 0, N_ELEMENTS(TEMP.RASTERS)-1 DO BEGIN GET_F_RASTER, TEMP.RASTERS(IR).RAS_ID, TEMP_R USE_GIS = USE_GIS OR (TEMP_R.DETECTOR EQ 'G') ENDFOR IF USE_GIS THEN BEGIN GET_GSET, DEF(I).GSET_ID, TEMP_G IF TEMP_G.GSET_ID LE 0 THEN BEGIN MESSAGE = 'GSET ID ' + TRIM(DEF(I).GSET_ID) + $ ' not found in database' GOTO, HANDLE_ERROR ENDIF ENDIF ENDIF ENDIF ; ; Make sure that the object code matches an entry in the database. ; GET_OBJECT, DEF(I).OBJECT, TEMP IF TEMP.OBJECT EQ '' THEN BEGIN MESSAGE = 'Object code ' + DEF(I).OBJECT + $ ' not found in database' GOTO, HANDLE_ERROR ENDIF IF I EQ 0 THEN OBJ = REPLICATE(TEMP,N_ELEMENTS(DEF)) ELSE $ OBJ(I) = TEMP ; ; Make sure that the stop date is greater than the start date. ; IF DEF(I).DATE_END LE DEF(I).DATE_OBS THEN BEGIN MESSAGE = 'The stop date must be after the start date' GOTO, HANDLE_ERROR ENDIF ENDFOR ; ; Reformat the times to millisecond accuracy. This is necessary so that ; the times are written out in a controlled way. ; DEF.DATE_OBS = DOUBLE( STRING( DEF.DATE_OBS, FORMAT='(F15.3)' )) DEF.DATE_END = DOUBLE( STRING( DEF.DATE_END, FORMAT='(F15.3)' )) ; ; Make sure that the proposed entries don't overlap with each other. ; FOR I = 0, N_ELEMENTS(DEF)-1 DO BEGIN W = WHERE((DEF(I).DATE_OBS LT DEF.DATE_END) AND $ (DEF(I).DATE_END GT DEF.DATE_OBS), COUNT) IF COUNT GT 1 THEN BEGIN MESSAGE = 'Proposed entries at time ' + $ TAI2UTC(DEF(I).DATE_OBS,/ECS,/TR) + ' to ' + $ TAI2UTC(DEF(I).DATE_END,/ECS,/TR) + ' and ' + $ TAI2UTC(DEF(W(1)).DATE_OBS,/ECS,/TR) + ' to ' + $ TAI2UTC(DEF(W(1)).DATE_END,/ECS,/TR) + $ ' overlap each other.' GOTO, HANDLE_ERROR ENDIF ENDFOR ; ; Open the science detailed database for write access. ; DBOPEN, 'sci_details', 1 ; ; Make sure that the proposed entries do not overlap any of the existing ; entries. ; MIN_DATE_OBS = MIN(DEF(W).DATE_OBS) MAX_DATE_END = MAX(DEF(W).DATE_END) ENTRIES = DBFIND('DATE_END>' + TRIM(MIN_DATE_OBS,'(F15.3)') + $ ',DATE_OBS<' + TRIM(MAX_DATE_END,'(F15.3)') + $ ',DELETED=N', /SILENT) IF !ERR EQ 0 THEN BEGIN N_FOUND = 0 END ELSE BEGIN ENTRIES = ENTRIES(UNIQ(ENTRIES)) N_FOUND = N_ELEMENTS(ENTRIES) DBEXT, ENTRIES, 'date_obs,date_end', DATE_OBS, DATE_END ENDELSE ; ; It's okay if the entries in the database only touches the time range of the ; new data. Start by sorting the entries by the start time, so that one only ; has to check the first and last entry. ; IF N_FOUND GT 0 THEN BEGIN IF N_FOUND GT 1 THEN BEGIN S = SORT(DATE_OBS) ENTRIES = ENTRIES(S) DATE_OBS = DATE_OBS(S) DATE_END = DATE_END(S) ENDIF IF DATE_OBS(N_FOUND-1) EQ MAX_DATE_END THEN $ N_FOUND = N_FOUND - 1 IF DATE_END(0) EQ MIN_DATE_OBS THEN N_FOUND = N_FOUND - 1 IF N_FOUND GT 0 THEN BEGIN MESSAGE = 'Definition would overlap one in the database' GOTO, HANDLE_ERROR ENDIF ENDIF ; ; Add the entries. ; DBBUILD, DEF.PROG_ID, DEF.STUDY_ID, DEF.STUDYVAR, DEF.SCI_OBJ, $ DEF.SCI_SPEC, DEF.CMP_NO, OBJ.OBJECT, DEF.OBJ_ID, $ DEF.DATE_OBS, DEF.DATE_END, DEF.ORIG_DUR, DEF.N_RASTERS1, $ DEF.TIME_TAGGED, DEF.TRACKING, DEF.N_POINTINGS, $ DEF.N_REPEAT_S, DEF.FLAG_MASTER, DEF.GSET_ID, DEF.GET_RAW, $ PROG_NUM, REPLICATE('N', N_ELEMENTS(DEF)), STATUS=STATUS IF STATUS EQ 0 THEN BEGIN MESSAGE = 'Write to sci_details database was not successful' GOTO, HANDLE_ERROR ENDIF ; ; Write the associated pointings. First, collect them into arrays. ; N_POINTINGS = 0 FOR I = 0, N_ELEMENTS(DEF)-1 DO BEGIN N = DEF(I).N_POINTINGS IF N GT 0 THEN BEGIN IF N_POINTINGS EQ 0 THEN BEGIN DATE_OBS = REPLICATE(DEF(I).DATE_OBS, N) POINT_IND = INDGEN(N) POINTINGS = DEF(I).POINTINGS(0:N-1) END ELSE BEGIN DATE_OBS = [DATE_OBS, REPLICATE(DEF(I).DATE_OBS, N)] POINT_IND = [POINT_IND, INDGEN(N)] POINTINGS = [POINTINGS, DEF(I).POINTINGS(0:N-1)] ENDELSE N_POINTINGS = N_POINTINGS + N ENDIF ENDFOR ; IF N_POINTINGS GT 0 THEN BEGIN DBOPEN, 'point_details', 1 DBBUILD, DATE_OBS, POINT_IND, POINTINGS.INS_X, POINTINGS.INS_Y, $ POINTINGS.ZONE_ID, REPLICATE('N', N_POINTINGS) ENDIF ; ; Signal success. ; RESULT = 1 GOTO, FINISH ; ; Error handling point. ; HANDLE_ERROR: IF N_ELEMENTS(ERRMSG) NE 0 THEN ERRMSG = 'ADD_DETAIL: ' + MESSAGE $ ELSE MESSAGE, MESSAGE, /CONTINUE ; ; Close the database, and return whether the routine was successful or not. ; FINISH: DBCLOSE ; RETURN, RESULT END