diff options
Diffstat (limited to 'noao/onedspec/ecidentify/eclinelist.x')
-rw-r--r-- | noao/onedspec/ecidentify/eclinelist.x | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/noao/onedspec/ecidentify/eclinelist.x b/noao/onedspec/ecidentify/eclinelist.x new file mode 100644 index 00000000..6653dd4b --- /dev/null +++ b/noao/onedspec/ecidentify/eclinelist.x @@ -0,0 +1,281 @@ +include <error.h> +include <mach.h> +include <smw.h> +include <units.h> +include "ecidentify.h" + +# EC_MAPLL -- Read the line list into memory. + +procedure ec_mapll (ec) + +pointer ec # Echelle pointer + +int fd, nalloc, nlines, open(), fscan(), nscan() +double value, lastval +pointer ec_ll +pointer sp, str, units, un_open() +bool streq() +errchk open, fscan, malloc, realloc, un_open + +begin + EC_LL(ec) = NULL + + call xt_stripwhite (Memc[EC_COORDLIST(ec)]) + if (Memc[EC_COORDLIST(ec)] == EOS) + return + iferr (fd = open (Memc[EC_COORDLIST(ec)], READ_ONLY, TEXT_FILE)) + return + + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (units, SZ_LINE, TY_CHAR) + call strcpy ("Angstroms", Memc[units], SZ_LINE) + + lastval = -MAX_DOUBLE + nalloc = 0 + nlines = 0 + while (fscan (fd) != EOF) { + call gargwrd (Memc[str], SZ_LINE) + if (nscan() != 1) + next + if (Memc[str] == '#') { + call gargwrd (Memc[str], SZ_LINE) + call strlwr (Memc[str]) + if (streq (Memc[str], "units")) { + call gargstr (Memc[units], SZ_LINE) + call xt_stripwhite (Memc[units]) + } + next + } + call reset_scan () + + call gargd (value) + if (nscan() != 1) + next + + if (nalloc == 0) { + nalloc = 100 + call malloc (ec_ll, nalloc, TY_DOUBLE) + } else if (nlines == nalloc) { + nalloc = nalloc + 100 + call realloc (ec_ll, nalloc, TY_DOUBLE) + } + + if (value < lastval) { + call close (fd) + call mfree (ec_ll, TY_DOUBLE) + call error (0, "Line list not sorted in increasing order") + } + + Memd[ec_ll+nlines] = value + nlines = nlines + 1 + } + call close (fd) + + if (nlines > 0) { + call realloc (ec_ll, nlines + 1, TY_DOUBLE) + Memd[ec_ll+nlines] = INDEFD + EC_LL(ec) = ec_ll + + if (EC_UN(ec) == NULL && Memc[units] != EOS) + EC_UN(ec) = un_open (Memc[units]) + call ec_unitsll (ec, Memc[units]) + } + + call sfree (sp) +end + + +# EC_UNMAPLL -- Unmap the linelist. + +procedure ec_unmapll (ec) + +pointer ec # Line list pointer + +begin + call mfree (EC_LL(ec), TY_DOUBLE) +end + + +# EC_UNITSLL -- Change the line list units from the input units to the +# units given by EC_UN. This may involve reversing the order of the list. + +procedure ec_unitsll (ec, units) + +pointer ec # Identify structure +char units[ARB] # Input units + +int i, nll +double value +pointer un, ll, llend, un_open() +bool un_compare() +errchk un_open + +begin + if (EC_LL(ec) == NULL) + return + if (IS_INDEFD(Memd[EC_LL(ec)])) + return + if (units[1] == EOS || EC_UN(ec) == NULL) + return + if (UN_CLASS(EC_UN(ec)) == UN_UNKNOWN) + return + + un = un_open (units) + if (un_compare (un, EC_UN(ec))) { + call un_close (un) + return + } + + ll = EC_LL(ec) + do i = 0, ARB + if (IS_INDEFD(Memd[ll+i])) { + nll = i + break + } + call un_ctrand (un, EC_UN(ec), Memd[ll], Memd[ll], nll) + call un_close (un) + + if (Memd[ll] > Memd[ll+nll-1]) { + llend = ll + nll - 1 + do i = 0, nll / 2 - 1 { + value = Memd[ll+i] + Memd[ll+i] = Memd[llend-i] + Memd[llend-i] = value + } + } +end + + + +# EC_MATCH -- Match current feature against a line list. + +procedure ec_match (ec, in, out) + +pointer ec # Echelle pointer +double in # Coordinate to be matched +double out # Matched coordinate + +double match, alpha, delta, delta1, delta2, out1 +pointer ll + +begin + if (EC_LL(ec) == NULL) { + out = in + return + } + + match = EC_MATCH(ec) + alpha = 1.25 + delta1 = MAX_REAL + + # Find nearest match. + for (ll=EC_LL(ec); !IS_INDEFD(Memd[ll]); ll = ll + 1) { + delta = abs (in - Memd[ll]) + if (delta < delta1) { + delta2 = delta1 + delta1 = delta + if (delta1 <= match) + out1 = Memd[ll] + } + } + + # Only return match if no other candidate is also possible. + if (delta1 > match) + return + if (delta2 < alpha * delta1) + return + + out = out1 +end + +# EC_LINELIST -- Add features from a line list. + +procedure ec_linelist (ec) + +pointer ec # Echelle pointer + +int i, line, ap, nfound, nextpix +double pix, fit, user, peak, minval, match, fit1, fit2 +pointer sp, aps, pixes, fits, users, peaks, ll + +double ec_center(), ec_fittopix(), ec_fitpt(), ec_peak() + +begin + if (EC_LL(ec) == NULL) + return + + call smark (sp) + call salloc (aps, EC_MAXFEATURES(ec), TY_INT) + call salloc (pixes, EC_MAXFEATURES(ec), TY_DOUBLE) + call salloc (fits, EC_MAXFEATURES(ec), TY_DOUBLE) + call salloc (users, EC_MAXFEATURES(ec), TY_DOUBLE) + call salloc (peaks, EC_MAXFEATURES(ec), TY_DOUBLE) + + nfound = 0 + minval = MAX_REAL + + do line = 1, EC_NLINES(ec) { + call ec_gline (ec, line) + ap = APS(ec,line) + fit1 = min (FITDATA(ec,1), FITDATA(ec,EC_NPTS(ec))) + fit2 = max (FITDATA(ec,1), FITDATA(ec,EC_NPTS(ec))) + for (ll=EC_LL(ec); !IS_INDEFD(Memd[ll]); ll = ll + 1) { + user = Memd[ll] + if (user < fit1) + next + if (user > fit2) + break + + pix = ec_center (ec, ec_fittopix (ec, user), EC_FWIDTH(ec), + EC_FTYPE(ec)) + if (!IS_INDEFD(pix)) { + fit = ec_fitpt (ec, ap, pix) + match = abs (fit - user) + if (match > EC_MATCH(ec)) + next + + peak = abs (ec_peak (ec, pix)) + if (nfound < EC_MAXFEATURES(ec)) { + nfound = nfound + 1 + if (peak < minval) { + nextpix = nfound + minval = peak + } + Memi[aps+nfound-1] = ap + Memd[pixes+nfound-1] = pix + Memd[fits+nfound-1] = fit + Memd[users+nfound-1] = user + Memd[peaks+nfound-1] = peak + } else if (peak > minval) { + Memi[aps+nextpix-1] = ap + Memd[pixes+nextpix-1] = pix + Memd[fits+nextpix-1] = fit + Memd[users+nextpix-1] = user + Memd[peaks+nextpix-1] = peak + + minval = MAX_REAL + do i = 1, nfound { + peak = Memd[peaks+i-1] + if (peak < minval) { + nextpix = i + minval = peak + } + } + } + } + } + } + call ec_gline (ec, EC_LINE(ec)) + + do i = 1, nfound { + ap = Memi[aps+i-1] + pix = Memd[pixes+i-1] + fit = Memd[fits+i-1] + user = Memd[users+i-1] + call ec_newfeature (ec, ap, pix, fit, user, EC_FWIDTH(ec), + EC_FTYPE(ec)) + } + + call sfree (sp) +end |