include include include "rvpackage.h" include "rvflags.h" include "rvsample.h" # SAMP_OPEN - Open a Sample structure. procedure samp_open (ssp) pointer ssp #I Sample struct pointer errchk calloc begin iferr (call calloc (ssp, SZ_SAMPSTRUCT, TY_STRUCT)) call error (0, "Error opening sample structure.") iferr { call calloc (SR_SRANGE(ssp), MAX_SAMPLES, TY_REAL) call calloc (SR_ERANGE(ssp), MAX_SAMPLES, TY_REAL) call calloc (SR_NPSAMP(ssp), MAX_SAMPLES, TY_INT) } then call error (0, "Error allocating sample structure.") end # SAMP_CLOSE - Close (free) a sample structure. procedure samp_close (ssp) pointer ssp #I Sample struct pointer begin if (ssp == NULL) return call mfree (SR_SRANGE(ssp), TY_REAL) call mfree (SR_ERANGE(ssp), TY_REAL) call mfree (SR_NPSAMP(ssp), TY_INT) SR_COUNT(ssp) = 0 call mfree (ssp, TY_STRUCT) end # RV_LOAD_SAMPLE - Given a string in 'ranges' format, decode it and load # the sample structure. Returns an ERR of OK. int procedure rv_load_sample (ssp, s) pointer ssp #I Sample struct pointer char s[ARB] #I Range string to parse pointer sp, buf, rv int ip, i, j, rcount, units int sample_units() begin call smark (sp) call salloc (buf, SZ_LINE, TY_CHAR) rv = SR_PARENT(ssp) ip = 1 if (!IS_DIGIT(s[ip])) ip = ip + 1 # Units specified rcount = 0 while (s[ip] != EOS) { rcount = rcount + 1 for (j=1; j<=2; j=j+1) { # Collect the numbers while (IS_WHITE(s[ip])) # Skip leading white space ip = ip + 1; call aclrs (Memc[buf], SZ_LINE) for (i=0; (s[ip]=='.'||IS_DIGIT(s[ip]))&&i MAX_SAMPLES) { call rv_errmsg (rv, "Cannot add another sample (max_samples=%d).") call pargi (MAX_SAMPLES) return } # Convert a wavelength range to pixels if necessary. if (SR_UNITS(ssp) == PIXELS && RV_DCFLAG(SR_PARENT(ssp)) != -1) { left = (log10(left) - SR_W0(ssp)) / SR_WPC(ssp) + 1 right = (log10(right) - SR_W0(ssp)) / SR_WPC(ssp) + 1 } # Now figure out what to do with it. Here we edit the existing # sample so they make more sense or else just add the range and # sort it. if (SR_COUNT(ssp) == ALL_SPECTRUM) { # special case SR_COUNT(ssp) = 1 SRANGE(ssp,1) = left ERANGE(ssp,1) = right if (RV_DCFLAG(rv) == -1 || RV_PIXCORR(rv) == YES) SR_UNITS(ssp) = PIXELS else SR_UNITS(ssp) = LAMBDA call rv_mark_regions (ssp, gp) return } do i = 1, SR_COUNT(ssp) { if (left >= SRANGE(ssp,i) && left <= ERANGE(ssp,i)) { j = 1 # Find the right side. while (j <= SR_COUNT(ssp)) { if (right >= SRANGE(ssp,j) && right <= ERANGE(ssp,j)) { if ((j-i) == 0) # within the same sample return else if ((j-i) == 1) { # in the next sample right = ERANGE(ssp,j) call rv_erase_regions (ssp, gp) call delete_samp (rv, ssp, SRANGE(ssp,j)) ERANGE(ssp,i) = right call sort_ranges (ssp) call rv_mark_regions (ssp, gp) return } else if ((j-i) > 1) { # skipped a few samples right = ERANGE(ssp,j) call rv_erase_regions (ssp, gp) do k = i+1, j-1 call delete_samp (rv, ssp, SRANGE(ssp,k)) ERANGE(ssp,i) = right call sort_ranges (ssp) call rv_mark_regions (ssp, gp) return } } j = j + 1 } if (j == SR_COUNT(ssp)+1) { # right is between samples call rv_erase_regions (ssp, gp) ERANGE(ssp,i) = right call rv_mark_regions (ssp, gp) return } } if (right >= SRANGE(ssp,i) && right <= ERANGE(ssp,i)) { call rv_erase_regions (ssp, gp) SRANGE(ssp,i) = left call rv_mark_regions (ssp, gp) return } } # The endpoints aren't included within another region. Let's see if # they then enclose one.... do i = 1, SR_COUNT(ssp) { if (SRANGE(ssp,i) >= left && SRANGE(ssp,i) <= right) { j = 1 while (j=ERANGE(ssp,j)) { j = j + 1 } if (j == i) { # in the next sample call delete_samp (rv, ssp, SRANGE(ssp,j)) } else if ((j-i) >= 1) { # skipped a few samples do k = i, j call delete_samp (rv, ssp, SRANGE(ssp,k)) } break } } # Just add it to the list. SR_COUNT(ssp) = SR_COUNT(ssp) + 1 SRANGE(ssp,SR_COUNT(ssp)) = left ERANGE(ssp,SR_COUNT(ssp)) = right call rv_mark_regions (ssp, gp) call sort_ranges (ssp) end # DELETE_SAMP - Delte a sample range from the list. procedure delete_samp (rv, ssp, x) pointer rv #I RV struct pointer pointer ssp #I Sample struct pointer real x #I WCS value of region to delete double dex() real l, r pointer gp int i, j begin gp = RV_GP(rv) if (SR_COUNT(ssp) == 1) { # special case call rv_erase_regions (ssp, RV_GP(rv)) SR_COUNT(ssp) = ALL_SPECTRUM return } # Find the sample to delete. if (SR_UNITS(ssp) == PIXELS && RV_DCFLAG(rv) != -1) x = (log10(x) - SR_W0(ssp)) / SR_WPC(ssp) + 1 do i = 1, SR_COUNT(ssp) { if (x >= SRANGE(ssp,i) && x <= ERANGE(ssp,i)) { if (SR_IMTYPE(ssp) == OBJECT_SPECTRUM) call gsview (gp, 0.115, 0.95, 0.51, 0.865) else if (SR_IMTYPE(ssp) == REFER_SPECTRUM) call gsview (gp, 0.115, 0.95, 0.125, 0.5) if (RV_PIXCORR(rv) == NO && RV_DCFLAG(rv) != -1 && SR_UNITS(ssp) == PIXELS) { l = real (dex(SR_W0(ssp)+(SRANGE(ssp,i)-1)*SR_WPC(ssp))) r = real (dex(SR_W0(ssp)+(ERANGE(ssp,i)-1)*SR_WPC(ssp))) } else { l = SRANGE(ssp,i) r = ERANGE(ssp,i) } call erase_range (gp, l, r) if (i == SR_COUNT(ssp)) { SR_COUNT(ssp) = SR_COUNT(ssp) - 1 } else { do j = i, SR_COUNT(ssp)-1 { SRANGE(ssp,j) = SRANGE(ssp,j+1) ERANGE(ssp,j) = ERANGE(ssp,j+1) } SR_COUNT(ssp) = SR_COUNT(ssp) - 1 } return } } end # MARK_RANGE - Mark the region selected on the screen with a bar. procedure mark_range (gp, left, right) pointer gp #I GIO pointer real left, right #I WCS of boundaries of region real x1, x2, y1, y2, y begin if (gp == NULL) return call ggwind (gp, x1, x2, y1, y2) y = y1 + (y2-y1)/20.0 # Put it near bottom 5% call gamove (gp, left, y) # Draw the horizontal bar call gadraw (gp, right, y) call gamove (gp, left, y1) # draw the cross bars at ends call gadraw (gp, left, y1+(2*(y-y1))) call gamove (gp, right, y1) call gadraw (gp, right, y1+(2*(y-y1))) call gflush (gp) end # ERASE_RANGE - Erase the range drawn to the screen. procedure erase_range (gp, left, right) pointer gp #I GIO pointer real left, right #I Range endpoints begin if (gp == NULL) return call gseti (gp, G_PLCOLOR, C_BACKGROUND) call mark_range (gp, left, right) call gseti (gp, G_PLCOLOR, C_FOREGROUND) end # SAMPLE_UNITS - Figure out what units the regions string is used in int procedure sample_units (str) char str[ARB] #I range specification string begin if (str[1] == 'a' || str[1] == 'A' || IS_DIGIT(str[1])) return (LAMBDA) else if (str[1] == 'p' || str[1] == 'P') return (PIXELS) else { return (ERR) } end # SORT_RANGES - Sort the ranges structure from left to right in terms of # regions to simplify masking process procedure sort_ranges (ssp) pointer ssp #I Sample struct pointer int i, j, npts real temp begin if (SR_COUNT(ssp) == 1 || SR_COUNT(ssp) == ALL_SPECTRUM) return # Now do a simple insertion sort of the ranges npts = SR_COUNT(ssp) do i = 2, npts { j = i while (SRANGE(ssp,j) < SRANGE(ssp,j-1)) { # Swap 'em temp = SRANGE(ssp,j-1) SRANGE(ssp,j-1) = SRANGE(ssp,j) SRANGE(ssp,j) = temp temp = ERANGE(ssp,j-1) ERANGE(ssp,j-1) = ERANGE(ssp,j) ERANGE(ssp,j) = temp j = j - 1 } } end