STScI Logo

t_sfit



include	<imhdr.h>
include <pkg/gtools.h>
include <pkg/rg.h>
include <math/curfit.h>
include	<error.h>
include	<smw.h>

# SFIT -- Fit a function to spectra and output the fit, difference or
# ratio; or print the power series coefficients of the fit.  The fitting
# parameters may be set interactively using the icfit package.

# Image header keywords for saving the previous fit

define	SFT_KW		"SFIT"
define	SFT_KWB		"SFITB"

# Choices for the type of output

define	OUT_TYPES	"|data|fit|difference|ratio|"

define	DATA		1
define	FIT		2
define	DIFFERENCE	3
define	RATIO		4

# Choices for the interactive prompts
# (the 1st define is for clgwrd (strdic), the 2nd for CL enumeration)
# Note that the CL assumes that the separator is `|'.

define	SFT_ANS1	"|yes|no|skip|YES|NO|SKIP|"
define	SFT_ANS1X	"yes|no|skip|YES|NO|SKIP"

define	SFT_ANS2	"|spectrum|image|all|cancel|"
define	SFT_ANS2X	"spectrum|image|all|cancel"

define	LEN_ANS		7

define	YES_ONCE	1
define	NO_ONCE		2
define	SKIP_ONCE	3
define	YES_ALWAYS	4
define	NO_ALWAYS	5
define	SKIP_ALWAYS	6

define	SKIP_SPEC	1
define	SKIP_IMAGE	2
define	SKIP_ALL	3
define	SKIP_CANCEL	4

# Switches and pointers

define	SFT_OFF		22

define	INTERACTIVE	Memi[$1]		# all spectra are noninteractive
define	REPLACE		Memi[$1+1]		# replace rejected points?
define	WAVESCALE	Memi[$1+2]		# X is wavelength if possible
define	LOGSCALE	Memi[$1+3]		# axes are logarithmic
define	OVERRIDE	Memi[$1+4]		# allow lines to be redone
define	LISTONLY	Memi[$1+5]		# don't modify images
define	OUTTYPE		Memi[$1+6]		# output type code

define	GRAPH_OPEN	Memi[$1+7]		# keep track of gopen
define	LOG_TO_STDOUT	Memi[$1+8]		# STDOUT/ERR is used
define	PROMPT		Memi[$1+9]		# prompt flag
define	QUIET		Memi[$1+10]		# quiet flag

define	RGIN		Memi[$1+11]		# lines specified
define	RGFIT		Memi[$1+12]		# all lines to fit
define	RGREFIT		Memi[$1+13]		# those to fit again
define	RGINB		Memi[$1+14]		# bands specified
define	RGFITB		Memi[$1+15]		# all bands to fit
define	RGREFITB	Memi[$1+16]		# those to fit again

define	NLOGFD		Memi[$1+17]		# number of logfiles
define	LOGFD		Memi[$1+18]		# array of logfiles

define	IC		Memi[$1+19]		# current ic descriptor
define	YMAX		Memi[$1+20]		# max number of lines
define	BMAX		Memi[$1+21]		# max number of lines
define	IC_DESC		Memi[$1+SFT_OFF+($3-1)*YMAX($1)+$2-1]	# ic descriptors


# T_SFIT -- Entry point for the task.  Read parameters,
# initialize structures and loop over the image templates.

procedure t_sfit ()

pointer	listin, listout, input, output, graphics
pointer	sf, gp, gt, in, out, mw, sh, sp
int	stat

int	sft_icfit(), imtgetim(), gt_init(), imtlen()
bool	clgetb()
pointer	imtopenp()

begin
	call smark (sp)
	call salloc (input, SZ_FNAME, TY_CHAR)
	call salloc (output, SZ_FNAME, TY_CHAR)
	call salloc (graphics, SZ_FNAME, TY_CHAR)

	# Open the image templates
	listin = imtopenp ("input")

	if (clgetb ("listonly"))
	    listout = NULL
	else {
	    listout = imtopenp ("output")
	    if (imtlen (listin) != imtlen (listout)) {
		call imtclose (listin)
		call imtclose (listout)
		call sfree (sp)
		call error (1, "Input and output image lists do not match")
	    }
	}

	# Initialize the various descriptors
	iferr (call sft_init (listin, listout, sf)) {
	    call imtclose (listin)
	    if (listout != NULL)
		call imtclose (listout)
	    call sfree (sp)
	    call erract (EA_ERROR)
	}

	# The graphics pointers are passed explicitly
	if (INTERACTIVE(sf) == YES) {
	    call clgstr ("graphics", Memc[graphics], SZ_FNAME)
	    gt = gt_init()
	    call gt_sets (gt, GTTYPE, "line")
	}

	# Fit the lines in each input image.

	while (imtgetim (listin, Memc[input], SZ_FNAME) != EOF) {

	    if (listout != NULL)
		stat = imtgetim (listout, Memc[output], SZ_FNAME)
	    else
		call strcpy (Memc[input], Memc[output], SZ_FNAME)

	    iferr {
		call sft_immap (Memc[input], Memc[output],
		    in, out, mw, sh, sf, gp)
	    } then {
		call erract (EA_WARN)
		next
	    }

	    stat = sft_icfit (in, out, mw, sh, sf, gp, gt, Memc[graphics])

	    call sft_unmap (in, out, mw, sh, sf)

	    if (stat == EOF)
		break
	}

	if (INTERACTIVE(sf) == YES)
	    call gt_free (gt)
	if (GRAPH_OPEN(sf) == YES)
	    call gclose (gp)

	call sft_close (sf)
	call imtclose (listin)
	if (listout != NULL)
	    call imtclose (listout)
	call sfree (sp)
end


# SFT_INIT -- Initialize templates, ranges, logfiles, type, icfit descriptors.

procedure sft_init (listin, listout, sf)

pointer	listin, listout		#I Image template descriptors
pointer	sf			#I Pointer to task switches

pointer	input, output, im, sp, mw
int	ymax, bmax, i, j

real	clgetr()
bool	clgetb()
int	clgwrd(), clgeti(), btoi(), strlen()
int	rg_next(), imtgetim(), imaccess(), xt_logopen()
pointer	rg_ranges(), immap(), smw_openim()
errchk	immap, smw_openim

begin
	call smark (sp)
	call salloc (input, SZ_LINE, TY_CHAR)
	call salloc (output, SZ_FNAME, TY_CHAR)

	sf = NULL
	iferr {

	    # find the maximum number of lines and bands (spectra)
	    ymax = 0
	    bmax = 0

	    while (imtgetim (listin, Memc[input], SZ_LINE) != EOF)
		if (imaccess (Memc[input], READ_ONLY) == YES) {
		    im = immap (Memc[input], READ_ONLY, 0)
		    mw = smw_openim (im)
		    ymax = max (SMW_LLEN(mw,2), ymax)
		    bmax = max (SMW_LLEN(mw,3), bmax)
		    call smw_close (mw)
		    call imunmap (im)
		}
	    call imtrew (listin)

	    if (listout != NULL) {
		while (imtgetim (listout, Memc[output], SZ_FNAME) != EOF)
		    if (imaccess (Memc[output], READ_ONLY) == YES) {
			im = immap (Memc[output], READ_ONLY, 0)
			mw = smw_openim (im)
			ymax = max (SMW_LLEN(mw,2), ymax)
			bmax = max (SMW_LLEN(mw,3), bmax)
			call smw_close (mw)
			call imunmap (im)
		    }
		call imtrew (listout)
	    }

	    # allocate space for the task switch structure
	    call malloc (sf, SFT_OFF + ymax * bmax, TY_STRUCT)

	    YMAX(sf) = ymax
	    BMAX(sf) = bmax

	    # NULL the pointers for error handling
	    RGIN(sf)	= NULL
	    RGINB(sf)	= NULL
	    NLOGFD(sf)	= 0
	    do j = 1, BMAX(sf)
		do i = 1, YMAX(sf)
		    IC_DESC(sf,i,j) = NULL

	    # Set the switches
	    INTERACTIVE(sf) = btoi (clgetb ("interactive"))
	    REPLACE(sf) = btoi (clgetb ("replace"))
	    WAVESCALE(sf) = btoi (clgetb ("wavescale"))
	    LOGSCALE(sf) = btoi (clgetb ("logscale"))
	    OVERRIDE(sf) = btoi (clgetb ("override"))
	    LISTONLY(sf) = btoi (clgetb ("listonly"))
	    GRAPH_OPEN(sf) = NO
	    PROMPT(sf) = INTERACTIVE(sf)
	    QUIET(sf) = btoi (INTERACTIVE(sf) == NO)

	    # Expand the range specification, allow either hyphens or colons

	    call clgstr ("lines", Memc[input], SZ_LINE)
	    do i = 1, strlen (Memc[input])
		if (Memc[input+i-1] == '-')
		    Memc[input+i-1] =  ':'
		else if (Memc[input+i-1] == 'x' || Memc[input+i-1] == 'X')
		    call error (1, "Range step (`x' notation) not implemented")

	    RGIN(sf) = rg_ranges (Memc[input], 1, YMAX(sf))
	    call rg_order (RGIN(sf))
	    call rg_merge (RGIN(sf))

	    call clgstr ("bands", Memc[input], SZ_LINE)
	    do i = 1, strlen (Memc[input])
		if (Memc[input+i-1] == '-')
		    Memc[input+i-1] =  ':'
		else if (Memc[input+i-1] == 'x' || Memc[input+i-1] == 'X')
		    call error (1, "Range step (`x' notation) not implemented")

	    RGINB(sf) = rg_ranges (Memc[input], 1, BMAX(sf))
	    call rg_order (RGINB(sf))
	    call rg_merge (RGINB(sf))

	    i = 0
	    j = 0
	    if (rg_next (RGIN(sf), i) == EOF || rg_next (RGINB(sf), j) == EOF)
		call error (1, "With range specification for `lines or bands'")
	    else {
		# Open the initial icfit descriptor
		call ic_open (IC(sf))

		call clgstr ("sample", Memc[input], SZ_LINE)
		call ic_pstr (IC(sf), "sample", Memc[input])
		call clgstr ("function", Memc[input], SZ_LINE)
		call ic_pstr (IC(sf), "function", Memc[input])

		call ic_puti (IC(sf), "naverage", clgeti ("naverage"))
		call ic_puti (IC(sf), "order", clgeti ("order"))
		call ic_putr (IC(sf), "low", clgetr ("low_reject"))
		call ic_putr (IC(sf), "high", clgetr ("high_reject"))
		call ic_puti (IC(sf), "niterate", clgeti ("niterate"))
		call ic_putr (IC(sf), "grow", clgetr ("grow"))
		call ic_puti (IC(sf), "markrej", btoi (clgetb ("markrej")))

		IC_DESC(sf,i,j) = IC(sf)
	    }

	    # Get the desired output type
	    OUTTYPE(sf) = clgwrd ("type", Memc[input], SZ_LINE, OUT_TYPES)

	    # Open the logfiles
	    NLOGFD(sf) = xt_logopen ("logfiles", "SFIT:", LOGFD(sf),
		LOG_TO_STDOUT(sf))

	} then {
	    call sfree (sp)
	    call sft_close (sf)
	    call erract (EA_ERROR)
	}

	call sfree (sp)
	return
end


# SFT_CLOSE -- Close the various descriptors.

procedure sft_close (sf)

pointer	sf			#I Pointer to task switches

int	i, j

begin
	if (sf != NULL) {
	    if (RGIN(sf) != NULL)
		call rg_free (RGIN(sf))
	    if (RGINB(sf) != NULL)
		call rg_free (RGINB(sf))
	    if (NLOGFD(sf) != 0)
		call xt_logclose (LOGFD(sf), NLOGFD(sf), "END:")
	    do j = 1, BMAX(sf)
		do i = 1, YMAX(sf)
		    if (IC_DESC(sf,i,j) != NULL)
			call ic_closer (IC_DESC(sf,i,j))
	    call mfree (sf, TY_STRUCT)
	}
end


# SFT_IMMAP -- Map images for sfit.

procedure sft_immap (input, output, in, out, mw, sh, sf, gp)

char	input[ARB]		#I Input image name
char	output[ARB]		#I Output image name
pointer	in, out			#O IMIO pointers
pointer	mw			#O MWCS pointer
pointer	sh			#O SHDR pointer
pointer	sf			#I Pointer for task switches
pointer	gp			#I GIO pointer

int	i, ax1, ax2, ax3
pointer	inroot, insect, outroot, outsect, b1, b2
pointer	sp, inranges, outranges
pointer	rgin, rgout, rgtmp, rgtmpb
long	v1[IM_MAXDIM], v2[IM_MAXDIM]
char	emsg[SZ_LINE]

int	imaccess(), imaccf(), imgnlr(), impnlr(), strcmp()
pointer	immap(), smw_openim()
pointer	rg_ranges(), rg_window(), rg_union(), rg_intersect()
errchk	immap, smw_openim

define	err_	13

begin
	call smark (sp)
	call salloc (inroot, SZ_FNAME, TY_CHAR)
	call salloc (insect, SZ_FNAME, TY_CHAR)
	call salloc (outroot, SZ_FNAME, TY_CHAR)
	call salloc (outsect, SZ_FNAME, TY_CHAR)
	call salloc (inranges, SZ_LINE, TY_CHAR)
	call salloc (outranges, SZ_LINE, TY_CHAR)

	in = NULL
	out = NULL
	mw = NULL
	sh = NULL
	RGFIT(sf) = NULL
	RGREFIT(sf) = NULL
	RGFITB(sf) = NULL
	RGREFITB(sf) = NULL

	call imgimage (input, Memc[inroot], SZ_FNAME)
	call imgsection (input, Memc[insect], SZ_FNAME)

	call imgimage (output, Memc[outroot], SZ_FNAME)
	call imgsection (output, Memc[outsect], SZ_FNAME)

	if (Memc[insect] != EOS || Memc[outsect] != EOS) {

	    call sprintf (emsg, SZ_LINE, "Sections not allowed (%s --> %s)")
		call pargstr (input)
		call pargstr (output)
	    goto err_

	} else if (imaccess (Memc[inroot], READ_ONLY) == NO) {

	    call sprintf (emsg, SZ_LINE, "Cannot access %s")
		call pargstr (input)
	    goto err_

	} else if (LISTONLY(sf) == YES) {

	    # The `out = in' allows the ranges code at the end of this
	    # procedure to cover all cases (with a little inefficiency).
	    # No check on the sizes of the input and output images.

	    in = immap (Memc[inroot], READ_ONLY, 0)
	    out = in

	} else if (strcmp (Memc[inroot], Memc[outroot]) == 0) {

	    # Overwrite the input image.
	    in = immap (Memc[inroot], READ_WRITE, 0)
	    out = in

	} else if (imaccess (Memc[outroot], READ_WRITE) == NO) {

	    in = immap (Memc[inroot], READ_ONLY, 0)
	    out = immap (Memc[outroot], NEW_COPY, in)
	    if (IM_PIXTYPE(out) != TY_DOUBLE)
		IM_PIXTYPE(out) = TY_REAL

	    # Do this since imcopy is unimplemented

	    call amovkl (long(1), v1, IM_MAXDIM)
	    call amovkl (long(1), v2, IM_MAXDIM)

	    while (imgnlr (in, b1, v1) != EOF && impnlr (out, b2, v2) != EOF)
		call amovr (Memr[b1], Memr[b2], IM_LEN(in, 1))

	} else {

	    in = immap (Memc[inroot], READ_ONLY, 0)
	    out = immap (Memc[outroot], READ_WRITE, 0)

	    # This relies on the axes beyond IM_NDIM(im) being unity

	    do i = 1, max (IM_NDIM(in), IM_NDIM(out))
		if (IM_LEN(in, i) != IM_LEN(out, i)) {
		    call sprintf (emsg, SZ_LINE, "%s & %s aren't the same size")
			call pargstr (Memc[inroot])
			call pargstr (Memc[outroot])
		    goto err_
		}

	}

	do i = 4, IM_NDIM(in)
	    if (IM_LEN(in, i) != 1) {
		call sprintf (emsg, SZ_LINE, "Too many dimensions for %s")
		    call pargstr (Memc[inroot])
		goto err_
	    }

	if (imaccf (in, SFT_KW) == YES)
	    call imgstr (in, SFT_KW, Memc[inranges], SZ_LINE)
	else
	    call strcpy ("", Memc[inranges], SZ_LINE)

	if (imaccf (out, SFT_KW) == YES)
	    call imgstr (out, SFT_KW, Memc[outranges], SZ_LINE)
	else {
	    call strcpy ("", Memc[outranges], SZ_LINE)
	    call imastr (out, SFT_KW, Memc[outranges])
	}

	mw = smw_openim (in)
	ax1 = SMW_LLEN(mw,1)
	ax2 = SMW_LLEN(mw,2)
	ax3 = SMW_LLEN(mw,3)

	rgin = rg_ranges (Memc[inranges], 1, ax2)
	rgout = rg_ranges (Memc[outranges], 1, ax2)
	rgtmp = rg_union (rgin, rgout)
	call rg_free (rgin)
	call rg_free (rgout)

	if (imaccf (in, SFT_KWB) == YES)
	    call imgstr (in, SFT_KWB, Memc[inranges], SZ_LINE)
	else
	    call strcpy ("", Memc[inranges], SZ_LINE)

	if (imaccf (out, SFT_KWB) == YES)
	    call imgstr (out, SFT_KWB, Memc[outranges], SZ_LINE)
	else {
	    call strcpy ("", Memc[outranges], SZ_LINE)
	    call imastr (out, SFT_KWB, Memc[outranges])
	}

	rgin = rg_ranges (Memc[inranges], 1, ax3)
	rgout = rg_ranges (Memc[outranges], 1, ax3)
	rgtmpb = rg_union (rgin, rgout)
	call rg_free (rgin)
	call rg_free (rgout)

	if (OVERRIDE(sf) == YES) {
	    RGFIT(sf) = rg_window (RGIN(sf), 1, ax2)
	    RGREFIT(sf) = rgtmp
	    RGFITB(sf) = rg_window (RGINB(sf), 1, ax3)
	    RGREFITB(sf) = rgtmpb
	} else {
	    call rg_inverse (rgtmp, 1, ax2)
	    RGFIT(sf) = rg_intersect (RGIN(sf), rgtmp)
	    RGREFIT(sf) = rg_ranges ("0", 1, 2)
	    call rg_free (rgtmp)
	    #call rg_inverse (rgtmpb, 1, ax3)
	    #RGFITB(sf) = rg_intersect (RGINB(sf), rgtmpb)
	    #RGREFITB(sf) = rg_ranges ("0", 1, 2)
	    #call rg_free (rgtmpb)
	    RGFITB(sf) = rg_window (RGINB(sf), 1, ax3)
	    RGREFITB(sf) = rgtmpb
	}

	if (RG_NPTS(RGFIT(sf)) <= 0) {
	    call sprintf (emsg, SZ_LINE, "No lines left to fit for %s")
		call pargstr (Memc[inroot])
	    goto err_
	}

	call sfree (sp)
	return

err_	call sfree (sp)
	call sft_unmap (in, out, mw, sh, sf)
	if (GRAPH_OPEN(sf) == YES) {
	    call gclose (gp)
	    GRAPH_OPEN(sf) = NO
	}
	# STDERR should get flushed AFTER closing graphics
	call error (1, emsg)
end


# SFT_UNMAP -- Unmap images for sfit.

procedure sft_unmap (in, out, mw, sh, sf)

pointer	in, out			#I IMIO pointers
pointer	mw			#I MWCS pointer
pointer	sh			#I SHDR pointer
pointer	sf			#I Task structure pointer

begin
	call shdr_close (sh)
	if (mw != NULL)
	    call smw_close (mw)
	if (out != NULL && out != in)
	    call imunmap (out)
	if (in != NULL)
	    call imunmap (in)
	if (RGFIT(sf) != NULL)
	    call rg_free (RGFIT(sf))
	if (RGREFIT(sf) != NULL)
	    call rg_free (RGREFIT(sf))
	if (RGFITB(sf) != NULL)
	    call rg_free (RGFITB(sf))
	if (RGREFITB(sf) != NULL)
	    call rg_free (RGREFITB(sf))
end


# SFT_ICFIT -- Given the image descriptors determine the fitting function
# for each line and output the fit, difference, ratio or coefficients.

int procedure sft_icfit (in, out, mw, sh, sf, gp, gt, graphics)

pointer	in, out				#I IMIO pointers
pointer	mw				#I MWCS pointer
pointer	sh				#I SHDR pointer
pointer	sf				#I Pointer for task switches
pointer	gp				#I GIO pointer
pointer	gt				#I GTOOLS pointer
char	graphics[ARB]			#I Graphics device

pointer	sp, wts, cv, data
int	line, band, i, j, n

int	sft_getline()
pointer	gopen(), imps3r()
real	sft_efncr()
extern	sft_efncr

begin
	call smark (sp)
	call salloc (wts, SMW_LLEN(mw,1), TY_REAL)

	line = 0
	band = 0
	while (sft_getline (in, mw, sh, sf, gt, line, band) != EOF) {

	    call amovkr (1., Memr[wts], SN(sh))

	    if (QUIET(sf) == NO) {
		if (GRAPH_OPEN(sf) == NO) {
		    gp = gopen (graphics, NEW_FILE, STDGRAPH)
		    GRAPH_OPEN(sf) = YES
		}
		call icg_fit (IC(sf), gp, "cursor", gt, cv, Memr[SX(sh)],
		    Memr[SY(sh)], Memr[wts], SN(sh))
	    } else
		call ic_fit (IC(sf), cv, Memr[SX(sh)], Memr[SY(sh)],
		    Memr[wts], SN(sh), YES, YES, YES, YES)

	    if (LISTONLY(sf) == NO) {
		i = LINDEX(sh,1)
		j = LINDEX(sh,2)
		n = SMW_LLEN(mw,1)
		switch (SMW_LAXIS(mw,1)) {
		case 1:
		    data = imps3r (out, 1, n, i, i, j, j)
		case 2:
		    data = imps3r (out, i, i, 1, n, j, j)
		case 3:
		    data = imps3r (out, i, i, j, j,  1, n)
		}
		if (SN(sh) < n)
		    call aclrr (Memr[data], n)

		switch (OUTTYPE(sf)) {
		case DATA:
		    if (REPLACE(sf) == YES)
			call ic_clean (IC(sf), cv, Memr[SX(sh)], Memr[SY(sh)],
			    Memr[wts], SN(sh))
		    call amovr (Memr[SY(sh)], Memr[data], SN(sh))
		    call sft_update (out, mw, line, band)
		case FIT:
		    call cvvector (cv, Memr[SX(sh)], Memr[data], SN(sh))
		    call sft_update (out, mw, line, band)
		case DIFFERENCE:
		    call cvvector (cv, Memr[SX(sh)], Memr[data], SN(sh))
		    if (REPLACE(sf) == YES)
			call ic_clean (IC(sf), cv, Memr[SX(sh)], Memr[SY(sh)],
			    Memr[wts], SN(sh))
		    call asubr (Memr[SY(sh)], Memr[data], Memr[data], SN(sh))
		    call sft_update (out, mw, line, band)
		case RATIO:
		    call cvvector (cv, Memr[SX(sh)], Memr[data], SN(sh))
		    if (REPLACE(sf) == YES)
			call ic_clean (IC(sf), cv, Memr[SX(sh)], Memr[SY(sh)],
			    Memr[wts], SN(sh))
		    call advzr (Memr[SY(sh)], Memr[data], Memr[data], SN(sh),
			sft_efncr)
		    call sft_update (out, mw, line, band)
		default:
		    call error (1, "bad switch in sft_icfit")
		}
	    }

	    call sft_power (in, line, cv, gp, sf)
	    call cvfree (cv)

	}

	# This terminates the cursor (GIN) mode echoplex suppression in
	# case the next sft_immap generates a password prompt from ZFIOKS.
	# Note that any such password prompt (from the kernel!) will
	# now show up on the status line, not the graphics plane.

	if (GRAPH_OPEN(sf) == YES) {
	    call printf ("\r")
	    call flush (STDOUT)
	}

	call sfree (sp)
	return (line)
end


# SFT_GETLINE -- Get image data to be fit.  Returns the line and band numbers.
# Returns EOF when done.

int procedure sft_getline (in, mw, sh, sf, gt, line, band)

pointer	in			#I IMIO pointer
pointer	mw			#I MWCS pointer
pointer	sh			#I SHDR pointer
pointer	sf			#I Pointer for task switches
pointer	gt			#I GTOOLS pointer
int	line			#U Line number
int	band			#U Band number

int	i
bool	waveok
char	ask[LEN_ANS]
pointer	linebuf, rg1, rg2, sp

int	clgwrd(), rg_next(), rg_inrange()
pointer	rg_ranges(), rg_intersect()
real	sft_efncr()
extern	sft_efncr
errchk	shdr_open

define	again_		99

begin
	call smark (sp)
	call salloc (linebuf, SZ_LINE, TY_CHAR)

	if (band == 0)
	    if (rg_next (RGFITB(sf), band) == EOF)
		return (EOF)

again_	if (rg_next (RGFIT(sf), line) == EOF) {
	    line = 0
	    if (rg_next (RGFITB(sf), band) == EOF)
		return (EOF)
	    goto again_
	}

	if (PROMPT(sf) == YES) {
	    call clprintf ("ask.p_min", "%s")
		call pargstr (SFT_ANS1X)

	    if (rg_inrange (RGREFIT(sf), line) == YES &&
		rg_inrange (RGREFITB(sf), band) == YES) {
		call clprintf ("ask.p_prompt",
		    "Refit [%d,%d] of %s w/ graph?        ")
	    } else {
		call clprintf ("ask.p_prompt",
		    "Fit [%d,%d] of %s w/ graph?          ")
	    }
	    call pargi (line)
	    call pargi (band)
	    call pargstr (IM_HDRFILE(in))

	    switch (clgwrd ("ask", ask, LEN_ANS, SFT_ANS1)) {

	    case YES_ONCE:
		QUIET(sf) = NO

	    case NO_ONCE:
		QUIET(sf) = YES

	    case SKIP_ONCE:
		goto again_

	    case YES_ALWAYS:
		QUIET(sf) = NO
		PROMPT(sf) = NO

	    case NO_ALWAYS:
		QUIET(sf) = YES
		PROMPT(sf) = NO

	    case SKIP_ALWAYS:
		call clprintf ("ask", "cancel")
		call clprintf ("ask.p_min", "%s")
		    call pargstr (SFT_ANS2X)
		call clprintf ("ask.p_prompt",
		    "Skip what?    (`all' to exit task)   ")

		switch (clgwrd ("ask", ask, LEN_ANS, SFT_ANS2)) {

		case SKIP_SPEC:
		    call clprintf ("ask", "yes")
		    # delete the spectrum from the list
		    call sprintf (Memc[linebuf], SZ_LINE, "%d")
			call pargi (line)

		    rg1 = rg_ranges (Memc[linebuf], 1, SMW_LLEN(mw,2))
		    call rg_inverse (rg1, 1, SMW_LLEN(mw,2))
		    rg2 = rg_intersect (RGIN(sf), rg1)
		    call rg_free (rg1)
		    call rg_free (RGIN(sf))

		    RGIN(sf) = rg2
		    goto again_

		case SKIP_IMAGE:
		    call clprintf ("ask", "yes")
		    return (EOF)

		case SKIP_ALL:
		    call clprintf ("ask", "yes")
		    return (EOF)

		case SKIP_CANCEL:
		    call clprintf ("ask", "yes")
		    line = line - 1
		    goto again_

		default:
		    call error (1, "bad switch (2) in sft_getline")

		}

	    default:
		call error (1, "bad switch (1) in sft_getline")

	    }

	}

	call shdr_open (in, mw, line, band, INDEFI, SHDATA, sh)

	if (LOGSCALE(sf) == YES)
	    call alogr (Memr[SY(sh)], Memr[SY(sh)], SN(sh), sft_efncr)

	if (WAVESCALE(sf) == YES) {
	    waveok = true
	} else
	    waveok = false

	if (!waveok)
	    do i = 1, SN(sh)
		Memr[SX(sh)+i-1] = i

	if (LOGSCALE(sf) == YES)
	    call alogr (Memr[SX(sh)], Memr[SX(sh)], SN(sh), sft_efncr)

	# Initialize and/or update the icfit descriptor

	if (IC_DESC(sf,line,band) == NULL) {
	    call ic_open (IC_DESC(sf,line,band))
	    call ic_copy (IC(sf), IC_DESC(sf,line,band))
	    #call ic_pstr (IC_DESC(sf,line,band), "sample", "*")
	}

	IC(sf) = IC_DESC(sf,line,band)

	call ic_putr (IC(sf), "xmin", min (Memr[SX(sh)], Memr[SX(sh)+SN(sh)-1]))
	call ic_putr (IC(sf), "xmax", max (Memr[SX(sh)], Memr[SX(sh)+SN(sh)-1]))

	if (QUIET(sf) == NO) {
	    if (waveok && LOGSCALE(sf) == YES) {
		call ic_pstr (IC(sf), "xlabel", "log wavelength")
		call ic_pstr (IC(sf), "ylabel", "log data")
	    } else if (LOGSCALE(sf) == YES) {
		call ic_pstr (IC(sf), "xlabel", "log column")
		call ic_pstr (IC(sf), "ylabel", "log data")
	    } else if (waveok) {
		call ic_pstr (IC(sf), "xlabel", "wavelength")
		call ic_pstr (IC(sf), "ylabel", "")
	    } else {
		call ic_pstr (IC(sf), "xlabel", "column")
		call ic_pstr (IC(sf), "ylabel", "")
	    }

	    call sprintf (Memc[linebuf], SZ_LINE, "%s, [%d,%d]\n%s")
		call pargstr (IM_HDRFILE(in))
		call pargi (line)
		call pargi (band)
		call pargstr (TITLE(sh))

	    call gt_sets (gt, GTTITLE, Memc[linebuf])
	}

	call sfree (sp)
	return (OK)
end


# SFT_EFNCR -- Called by advzr on division by zero or by alogr for a
# zero or negative argument.

real procedure sft_efncr (x)

real	x

begin
	return (0.)
end


# SFT_POWER -- Transform the curfit output into a power series and
# print the coefficients to the logfiles.  This should be modified to
# print the errors as well.  That requires modifying the curfit routine
# cvpower to deal with errors; and adding an icfit routine (or include
# file define) that allows access to the dynamic arrays of sample points
# that are initialized if the sample is less than the whole set of points.

procedure sft_power (im, line, cv, gp, sf)

pointer	im			#I IMIO descriptor for labeling
int	line			#I Image line number for labeling
pointer	cv			#I CURFIT pointer
pointer	gp			#I GIO pointer for tidy output
pointer sf			#I Pointer for task switches

pointer	ps_coeff, linebuf, sp
int	ncoeffs, i, j, fd

int	cvstati(), strcmp()

begin
	if (NLOGFD(sf) <= 0)
	    return

	call smark (sp)
	call salloc (linebuf, SZ_LINE, TY_CHAR)

	# cvpower only works with legendre or chebyshev functions

	call ic_gstr (IC(sf), "function", Memc[linebuf], SZ_LINE)
	if (strcmp (Memc[linebuf], "legendre") != 0 &&
	    strcmp (Memc[linebuf], "chebyshev") != 0) {
	    call sfree (sp)
	    return
	}

	if (GRAPH_OPEN(sf) == YES && LOG_TO_STDOUT(sf) == YES) {
	    call gclose (gp)
	    GRAPH_OPEN(sf) = NO
	}

	ncoeffs = cvstati (cv, CVNCOEFF)
	call salloc (ps_coeff, ncoeffs, TY_REAL)
	call cvpower (cv, Memr[ps_coeff], ncoeffs)

	do i = 1, NLOGFD(sf) {
	    fd = Memi[LOGFD(sf)+i-1]

	    call fprintf (fd, "Line %d of %s:\n\n")
		call pargi (line)
		call pargstr (IM_HDRFILE(im))

	    call fprintf (fd, "      coeff           value\n")

	    do j = 1, ncoeffs {
		call fprintf (fd, "\t%d\t%12.5e\n")
		    call pargi (j)
		    call pargr (Memr[ps_coeff+j-1])
	    }

	    call fprintf (fd, "\n")
	    call flush (fd)
	}

	call sfree (sp)
end


# SFT_UPDATE -- Update the keyword with completed spectrum.  Flush the pixels.

procedure sft_update (im, mw, line, band)

pointer	im			#I IMIO pointer
pointer	mw			#I MWCS pointer
int	line			#I Line just completed
int	band			#I Band just completed

pointer linebuf, rg1, rg2, rgold, sp

pointer	rg_ranges(), rg_union()

begin
	call smark (sp)
	call salloc (linebuf, SZ_LINE, TY_CHAR)

	# this could be recoded to use "rg_add"

	call sprintf (Memc[linebuf], SZ_LINE, "%d")
	    call pargi (line)
	rg1 = rg_ranges (Memc[linebuf], 1, SMW_LLEN(mw,2))

	call imgstr (im, SFT_KW, Memc[linebuf], SZ_LINE)
	rg2 = rg_ranges (Memc[linebuf], 1, SMW_LLEN(mw,2))

	rgold = rg_union (rg1, rg2)
	call rg_encode (rgold, Memc[linebuf], SZ_LINE)
	call impstr (im, SFT_KW, Memc[linebuf])

	call rg_free (rg1)
	call rg_free (rg2)
	call rg_free (rgold)

	call sprintf (Memc[linebuf], SZ_LINE, "%d")
	    call pargi (band)
	rg1 = rg_ranges (Memc[linebuf], 1, SMW_LLEN(mw,3))

	call imgstr (im, SFT_KWB, Memc[linebuf], SZ_LINE)
	rg2 = rg_ranges (Memc[linebuf], 1, SMW_LLEN(mw,3))

	rgold = rg_union (rg1, rg2)
	call rg_encode (rgold, Memc[linebuf], SZ_LINE)
	call impstr (im, SFT_KWB, Memc[linebuf])

	call rg_free (rg1)
	call rg_free (rg2)
	call rg_free (rgold)

	call imflush (im)
	call sfree (sp)
end

Source Code · Search Form · STSDAS