;+ ; NAME: ; oc_getline_2mass ; ; PURPOSE: (one line) ; Return catalog line from the 2MASS catalog ; ; DESCRIPTION: ; Routine is passed a 2MASS ID or ID's. It uses this to search through ; a lookup table to determine the record location for that star. ; It then reads that record from the full uncompressed version of the ; 2MASS catalog. ; ; CATEGORY: ; Star catalogs ; ; CALLING SEQUENCE: ; lines = oc_getline_2mass( ids [, NSTARS=nstars] [, /VERBOSE]) ; ; INPUTS: ; IDs -- A list of 2MASS ID's. Scalar or vector. String. ; IDs must be in standard 2MASS format. ; ; OPTIONAL INPUT PARAMETERS: ; None ; ; KEYWORD INPUT PARAMETERS: ; None ; ; KEYWORD OUTPUT PARAMETERS: ; NSTARS -- Returns the number of successfully-retrieved lines. ; /VERBOSE -- If set, print diagnostics to screen. ; ; OUTPUTS: ; If input is a scalar, then output is a single string. ; If input is a vector, then output is an array of strings. ; If a star is not found, returned value is ''. ; ; COMMON BLOCKS: ; common_2mass ; ; SIDE EFFECTS: ; None ; ; RESTRICTIONS: ; 2MASS uncompressed catalog must be at $TMC_PATH/dvd/uncompress ; 2MASS lookup tables must be at $TMC_PATH/lookup, ; made by make_lookup_2mass.pro ; ; EXAMPLE: ; print, oc_getline_2mass(['00583149-8955091', '00583149-8955090']) ; prints '14631211|89.919197|0.07', '' ; ; MODIFICATION HISTORY: ; Written 18-May-2006 by H. Throop, SwRI ; ;- ;;;;;;;;;; pro oc_getline_2mass_searchfile, bin, id, id1, id2, ra, dec, $ POS_out=pos_out, num_out=num_out, NSTARS=nstars ; This routine does the binary search through the 2MASS catalog. ; Returns line number of match. It is not an end-user routine. common common_2mass, dir_lookup, bin_dec_min, bin_dec_max, extension, $ bytes_per_line, num_lines_cat, EMPTY DEC_PER_RA = 5 ; An assumption of the max number of ; stars with same initial ID component. file = strcompress( dir_lookup + '/' + '2mass_' + $ string(bin_dec_min[bin],format='(F5.1)') + '_' + $ string(bin_dec_max[bin],format='(F5.1)') + extension, $ /remove) openr, lun, file, /GET_LUN ; print, 'Opening file ' + file num_lines_cat= (fstat(lun)).size / BYTES_PER_LINE ; Take a first guess at the location within the file id1_in = 0L id2_in = 0L filenum_in = 0 filepos_in = 0L filenum_out = EMPTY filepos_out = 0d ; Set up parameters for the search done = 0 start = long(num_lines_cat/2d) ; Start in the middle j_min = 0 j_max = num_lines_cat-1 j = start j_last1 = 0 j_last2 = 0 ; Now we do a search through the catalog. We start in the middle. If we're ; too high, we go earlier in the catalog by half, and vice/versa. We do this ; until we have found the proper star. We should be able to find any star ; within log_2(n_lines) steps. repeat begin ; Save the earlier locations j_last2 = j_last1 j_last1 = j point_lun, lun, j * BYTES_PER_LINE readu, lun, id1_in, id2_in, filenum_in, filepos_in; 14 bytes: LLIL id_line = string(id1_in) ; print ; print, 'j = ' + st(j) + ' / ' + st(num_lines_cat) + $ ; '; currently at ' + string(id1_in + id2_in/1d7, format='(F19.7)') + $ ; ', looking for ' + string(id1 + id2/1d7, format='(F19.7)') ; We found the RA properly. Usually this is unique, but formally, ; there may be a few stars with that RA, so we now search by dec. if (id1 eq id1_in) then begin offset = -DEC_PER_RA done = 0 ; Now search for Dec point_lun, lun, ((j+offset)>0) * BYTES_PER_LINE ; Clear EOF flag while not(eof(lun)) and (offset++ lt DEC_PER_RA) and (not done) do $ begin point_lun, lun, ((j+offset)>0) * BYTES_PER_LINE readu, lun, id1_in, id2_in, filenum_in, filepos_in; 14 bytes: LLIL if (long(id1_in) eq long(id1)) and (long(id2_in) eq long(id2)) $ then begin filepos_out = filepos_in ; Return position read from file filenum_out = filenum_in done = 1 nstars++ ; print, 'done!' end end if not(done) then begin done = -1 ; Failed the search ; print, 'Gave up -- found RA but not dec!' ; stop end end ; RA here is too low -- move to later in list. ; We search by RA, which is id1, which is sorted. if (id1 gt id1_in) then begin j_min = j j = long((j + j_max)/2d + 0.5) ; print, 'moving later. j_min=' + st(j_min) + ', j = ' + st(j) + $ ; ', j_max = ' + st(j_max) end ; RA here is too high -- move to earlier in list if (id1 lt id1_in) then begin j_max = j j = long((j + j_min)/2d) ; print, 'moving earlier. j_min=' + st(j_min) + ', j = ' + st(j) + $ ; ', j_max = ' + st(j_max) end ; Didn't find the star if (((j eq j_last1) or (j eq j_last2)) and (not done)) $ or (j ge num_lines_cat) then begin filenum_out = EMPTY done = -1 ; print, 'Gave up, since j=' + st(j) end end until (abs(done) eq 1) ; Loop for binary tree close, lun & free_lun, lun if (done eq 1d) then begin pos_out = filepos_out num_out = filenum_out end if (done eq -1d) then begin pos_out = EMPTY num_out = EMPTY end end ; oc_getline_2mass_searchfile ;;;;;;;;;; function oc_getline_2mass, ids, VERBOSE=verbose, NSTARS=nstars ; This routine is the external entry routinefor 2mass binary searching. ; The searching is not done here. This routine is setup so that ; if a star is not found, the preceding and post-ceding files are searched ; as well. This is not to address sorting errors, but to address ; stars whose DEC bin cannot be uniquely determined from their ID, ; due to rounding ambuguities. common common_2mass d2r = 2*!dpi / 360d r2d = 1/d2r bytes_per_line = 14L extension = '.bin' nstars = 0 EMPTY = -999d dir_2mass = getenv('TMC_PATH') dir_lookup = str_replace(dir_2mass, 'dvd', 'lookup') dir_uncompress = dir_2mass + '/uncompress' bin_dec_min = (frange(-90d, +90d, 1801))[0:1799] bin_dec_max = (frange(-90d, +90d, 1801))[1:1800] ; Get file list, excluding things like 'psc_bbf.lookup' files_2mass = findfile(dir_uncompress + '/' + 'psc_???') numids = sizex(ids) filenum_out = intarr(numids) filepos_out = lonarr(numids) lines_out = strarr(numids) ; Loop over the star ID's passed in for i = 0, numids-1 do begin id = ids[i] id1 = strmid(id, 0, 8) ; RA id2 = strmid(id, 8, 8) ; Dec ra_h = double(strmid(id1, 0, 2)) ra_m = double(strmid(id1, 2, 2)) ra_s = double(strmid(id1, 4, 4)/100d) dec_si = strmid(id2, 0, 1) if (dec_si eq '-') then dec_si = -1 $ else if (dec_si eq '+') then dec_si = +1 dec_d = double(strmid(id2, 1, 2)) dec_m = double(strmid(id2, 3, 2)) dec_s = double(strmid(id2, 5, 3)/10d) hmstorad, ra_h, ra_m, ra_s, ra & ra *= r2d dmstorad, dec_si, dec_d, dec_m, dec_s, dec & dec *= r2d bin = max(where(dec ge bin_dec_min)) ; Which dec bin are we in? ; Now perform the actual search oc_getline_2mass_searchfile, $ bin, $ id, id1, id2, ra, dec, pos_out=pos_out, num_out=num_out, NSTARS=nstars ; In *very rare* cases (e.g., 00004570+0018000), the bin cannot be ; determined from the ID, due to possible rounding. In these cases, ; we must search bounding files. if (num_out eq EMPTY) then oc_getline_2mass_searchfile, $ (bin+1) < (sizex(bin_dec_max)-1), $ id, id1, id2, ra, dec, pos_out=pos_out, num_out=num_out, NSTARS=nstars if (num_out eq EMPTY) then oc_getline_2mass_searchfile, $ (bin-1)>0, id, $ id1, id2, ra, dec, pos_out=pos_out, num_out=num_out, NSTARS=nstars filepos_out[i] = pos_out filenum_out[i] = num_out end ; Now that we have located the line number for each star, read in the lines. line = '' for i = 0, numids-1 do begin if (filenum_out[i] eq EMPTY) then begin lines_out[i] = '' if (keyword_set(VERBOSE)) then print, $ 'Error: star ' + id + ' not found in 2MASS catalog' end else begin openr, lun, files_2mass[filenum_out[i]], /get_lun point_lun, lun, filepos_out[i] readf, lun, line & lines_out[i] = line close, lun & free_lun, lun end end ; stop return, lines_out end ;;;;;;;;;;