diff options
Diffstat (limited to 'noao/twodspec/apextract')
114 files changed, 22426 insertions, 0 deletions
diff --git a/noao/twodspec/apextract/Revisions b/noao/twodspec/apextract/Revisions new file mode 100644 index 00000000..3ffe9058 --- /dev/null +++ b/noao/twodspec/apextract/Revisions @@ -0,0 +1,1558 @@ +.help revisions Jun88 noao.twodspec.apextract +.nf + +approfile.x + When an aperture goes off the edge of an image there was an error + which allowed the imio data buffer from the image to go out of bounds. + (3/12/13, MJF) + +aptrace.x + The line1/line2 variables weren't being initialized to zero in the + ap_ctrace() procedure. This woule lead to old values from a previous + run of the task being reused. (2/6/13, MJF) + +======= +V2.16.1 +======= + +approfile.x + Fixed a bug in the Marsh algorithm causing segfaults on 64-bit + platforms (Buglog 583) (3/5/12, Valdes) + +apall.par + Changed the default for maxsep from 1000 to 100000. This is because + the default is when the user doesn't want to skip apertures and it is + strange when the id jumps in the (rare) case that two apertures are + marked with a separation of more than 1000. (2/17/09, Valdes) + +apedit.x + The 's' key now works on the current aperture rather than the nearest. + (10/7/08, Valdes) + +apcolon.x + The "all" mode was missing with :center. (10/7/08, Valdes) + +apall1.par +apfit1.par +apnoise1.par +apnorm1.par +apscat1.par +apparams.dat + When the apertures parameter was added in 1996 the :apertures and + :parameters commands were broken because of missing references in + the associated hidden psets. (10/7/08, Valdes) + +======= +V2.14.1 +======= + +======== +V2.12.2a +======== + +apextract.x + When using APFIT to output the difference the IMIO buffer which was + assumed to be static was invalidated because of I/O needed to create + the difference. A special case was added to handle this case. + (7/7/04, Valdes) + +apcveval.x + +apedit.x +apextract.x +apfind.x +apfindnew.x +apfit.x +apgmark.x +apgscur.x +apmask.x +apnoise.x +apprint.x +approfile.x +aprecenter.x +apresize.x +apskyeval.x +apupdate.x +apvalues.x +apvariance.x +apnearest.x +apscatter.x +aptrace.x +mkpkg + Added an interface routine to CVEVAL to avoid calling it with + independent variables outside the range of the fit. The fit range + may be short because of tracing problems. So the profile shift + is now extended from the end points of the fitted range. + (5/21/04, Valdes) + +apupdate.x +apdefault.x +apfind.x +aptrace.x +apedit.x +apcolon.x + Modified to check for inappropriate INDEF values in the "lower" + and "upper" aperture settings. (3/26/04, Valdes) + +======= +V2.12.2 +======= + +apextract.x + The edge weighting interpolation buffer space, interpbuf, was + increased by one pixel. This makes the data buffer wider so that + interpolation avoids using boundary extension except in cases where the + aperture actually approaches the image edge. Note that this change + results in an improvement in the extracted spectra over the previous + release where wraparound boundary extension was used. This also means + extractions will not be identical between the versions. + (1/23/04, Valdes) + +apextract.x + The new routine ap_asifit was not correct. (1/22/04, Valdes) + +apextract.x +approfile.x +apvariance.x + A problem related to the change of 10/21/03 is when the trace goes + far outside the data buffer. This could result in the number of points + specified for asifit being too small for the interpolation function. + An interface routine, ap_asifit, was added to do all the checks related + to using asifit for evaluating the edge pixels. (12/10/03, Valdes) + +=========== +V2.12.2BETA +=========== + +apextract.x + The output name based on the input name for multiextension images + produces a multiextension output with the same extension description. + (12/3/03, Valdes) + +apgetim.x + 1. Restored ability to use image sections which was lost in the change + on 7/13/98 for V2.11.2. + 2. Support for multiextension data was added. This consists of using + a standard name based on EXTNAME and EXTVER and without the + file type extension. Note that this means that image names specified + by index will be converted to extension name and extension version. + (12/3/03, Valdes) + +apextract.x +approfile.x +apvariance.x + The call to asifit was specifying too many points to fit, a whole line + in the data buffer, because the data vector may be offset from the first + column of the data buffer. This could cause a segmentation violation. + (10/21/03, Valdes) + + +apwidth.cl + Script to compute aperture widths from database. This was written + for a user and is saved here though it is not currently defined by + default. (12/2/02, Valdes) + +apflat1.par + The indirect reference needs to be spelled out without abbreviation to + be "apflatten" instead of "apflat". (11/18/02, Valdes) + +======= +V2.12.1 +======= + +apextract.x +approfile.x +apvariance.x + Modified to handle edge pixels by interpolation. (6/19/02, Valdes) + +===== +V2.12 +===== + +apgraph.x +apgmark.x + When there is just one aperture the background regions are marked + in apedit and in plotfile output. (9/21/01, Valdes) + +doc/apall.hlp + The help page was indicating the extra information output was the + variance rather than the sigma. (8/19/00, Valdes) + +apextract.x + The checking for the maximum number of apertures that fit in the allocated + memory (the "do j = i, napsex" loop) was incorrect because i was used + instead of the loop index j. (3/20/00, Valdes) + +========= +V2.11.3p1 +========= +======= +V2.11.3 +======= + +approfile.x + In the previous change to the weights in the Horne algorithm + the behavior when all data is rejected (say because the background + is set wrong and all data is below the background) the weights + would be set to MAX_REAL/10 which would cause CVFIT to fail. + (3/13/00, Valdes) + +apall1.par +apdebug.par +apfit1.par +apnoise1.par +apnorm1.par +apparams.par + Reduced the polysep parameter. (1/26/00, Valdes) + +apextractbak.x - +mkpkg + Removed this second old copy which was accidentally introduced into + mkpkg as well resulting in multiple copies of the same procedures + in the library in V2.11.3beta. (12/9/99, Valdes) + +doc/apflatten.hlp + Removed extraneous parameters not actually in task parameter set. + (10/21/99, Valdes) + +mkpkg + Added missing dependencies. (10/11/99, Valdes) + +======= +V2.11.2 +======= + +apextract.x + Added a keyword SUBAP when using echelle output with subapertures. + (3/26/99, Valdes) + +apflatten.par +apflat1.par + Removed background subtraction as an option. (12/11/98, Valdes) + +apskyeval.x + If the background sample region does not have explicit regions then + the xmin/xmax region is used for the background. (12/11/98, Valdes) + +apfit.x + Added errchk for ic_fit and ic_gfit. (12/8/98, Valdes) + +apflat1.par + Reduced the polysep because it can go wrong. (12/8/98, Valdes) + +apextract.x + Added check to fix cases with the lower and upper aperture limits + are reversed. + (7/13/98, Valdes) + +apgetim.x + Changed to call xtools routine that strips extensions. + (7/13/98, Valdes) + +approfile.x + In the Horne algorithm the weights for rejected points were set to zero + to eliminate them from the fit. But if large regions are rejected + this leaves the fit unconstrained and can lead to bad results. A + change was made to set the weights for the rejected points to 1/10 + of the minimum weight for the good data. + (2/6/98, Valdes) + +apextract.x + For "echelle" format with "extras" the header was not setup properly + resulting in WCSDIM=2 instead of 3. (2/6/98, Valdes) + +apids.x + 1. Fix bug in IDS structure which pointed outside of allocated memory. + 2. Variables ra/dec in ap_gids were being used both as pointers and + double. The ra/dec pointer usage was removed. + 3. The realloc step at the end of ap_gids had the wrong check so it + would never be done. + (1/13/98, Valdes) + +======= +V2.11.1 +======= +===== +V2.11 +===== + +doc/apsum.hlp +doc/apsum.hlp + Added missing task name in revisions section. (4/22/97, Valdes) + +apextract.x + Removed calls to impl from inside amove in order to error check them. + (1/24/97, Valdes) + +t_apall.x + 1. Added errchk for ap_dbwrite. + 2. Made writing the aplast file optional. + 3. It is a warning if the plot file can't be written. + (1/24/97, Valdes) + +apextract.x + The step where the data is multplied by the gain was multiplying + outside the data if dispaxis=1. If the there are enough apertures + and the aperture widths decrease then it is possible to get + mulitplications of gain**naps which can cause a floating overflow. + This was fixed. (11/12/96, Valdes) + +apertures.h +t_apall.x +aptrace.x +apresize.x +apalloc.x +apextract.x +apselect.x +aprecenter.x +apall.par +apall1.par +apfit1.par +apflat1.par +apnorm1.par +apparams.par +apnoise1.par +apdebug.par +apfit.par +apflatten.par +apmask.par +apnoise.par +apnormalize.par +apresize.par +apscatter.par +apsum.par +aptrace.par +apedit.par +apfind.par +aprecenter.par +mkpkg +doc/apextract.hlp +doc/apextras.hlp +doc/apedit.hlp +doc/apall.hlp +doc/apfind.hlp +doc/apresize.hlp +doc/apsum.hlp +doc/aptrace.hlp +doc/apfit.hlp +doc/apflatten.hlp +doc/apmask.hlp +doc/apnoise.hlp +doc/apnormalize.hlp +doc/aprecenter.hlp +doc/apscatter.hlp + Added a new parameter "apertures" to select a subset of the apertures + to resize, recenter, trace, extract, etc. The parameter "apertures" + which applied to the recentering was changed to "aprecenter". + (9/5/96, Valdes) + +apedit.key + Alphabetized the summary command lists. (9/3/96, Valdes) + +apextract.x + 1. Onedspec output format is now allowed when nsubaps is greater than 1. + 2. Echelle format outputs all orders for a each subapertures in + separate files. + (4/3/96, Valdes) + +apmw.x +apextract.x + The WCS for strip extraction was wrong. (1/31/96, Valdes) + +apmw.x + An error in computing the WCS transformation now prints a more informative + message indicating the final extracted spectrum will be in pixel units. + (1/4/96, Valdes) + +apids.x +apedit.x + Changed the behavior of the 'i' and 'o' keys with regard to the beam + numbers. These keys will now assign a beam number from the apid table + for the selected aperture as well as all other apertures. Previously + the beam number was not changed which resulted in a new aperture + number with a beam number that did not agree with the apid table. + (10/27/95, Valdes) + +doc/apextras.hlp + +apextract.men +apextract.hd + Added a help topic on the "extras" information. (9/5/95, Valdes) + +apimmap.x + If the image header dispersion axis is unreasonable a warning is + printed and the "dispaxis" parameter is used instead. (8/2/95, Valdes) + +apids.x +apmw.x +doc/apall.hlp +doc/apdefault.hlp +doc/apedit.hlp +doc/apfind.hlp + Modified to allow aperture ID table to be from an image header + under the keywords SLFIBnnn. The extracted image will have + these keywords deleted. (7/25/95, Valdes) + +======= +V2.10.4 +======= + +apscatter.x + When not smoothing along the dispersion there was a bug that when + the number of points being fit across the disperision changed + ICFIT was not reset causing an error "Range descriptor undefined". + The routine now reset the "new" flag when the number of points + changes. (5/3/95, Valdes) + +t_apall.x + Using the same input and output image name in APSCATTER was still + not right. (2/24/95, Valdes) + +apscatter.x + Made the output image datatype be at least real. (2/23/95, Valdes) + +apextract.x + For normalization the weights were not forced causing the gain to + default to 0. The change of 12/31/94 also fixed this by setting the + gain to 1. The file was touched but not changed. (1/27/95, Valdes) + +apextract.x +apskyeval.x + Made the query for the readnoise only occur if needed. Previously + the query was made in the sky step even if the sky error estimate + was not needed. (12/31/94, Valdes) + +apedit.x + Needed to set clobber and review options so they are queried during + interactive extraction. (10/28/94, Valdes) + +apimmap.x +apgetim.x +apgetdata.x +apextract.x +apmw.x + 1. If a 3D image is given then a warning is printed and the first plane + is used and the other planes are ignored. + 2. Various fixes to allow image sections to be used. + (10/12/94, Valdes) + +aptrace.x + An uninitialized memory problem was fixed. (9/19/94, Valdes/Zarate) + +apicset.x + Fixed type mismatch in min/max function calls. (6/13/94, Valdes/Zarate) + +apextract.x + Changed BANDID name for raw spectrum to "raw". (5/3/94, Valdes) + +apvariance.x +doc/apvariance.hlp +doc/apall.hlp +doc/apsum.hlp + The correction to bring the weighted and unweighted total fluxes to the + same value (called the bias factor) can produce odd values in special + cases; such as slitlets where only part of the image contains real + spectrum. This could result in variance spectra with flux scaling + errors to the extreme of a negative (inverted) spectrum. The bias + factor is now logged. If the two total fluxes differ by more than a + factor of 2 a warning (which always appears on the standard output) is + given with the fluxes and the bias factor. If the bias factor is + negative a warning is given and the bias factor is ignored. + (5/1/94, Valdes) + +doc/aptrace.hlp + Fixed typo in description of Legendre basis functions. (4/1/94, Valdes) + +apextract.x +doc/apextract.hlp + Added output BANDID keywords to document the various output data. + (2/4/94, Valdes) + +apnoise.x + +apnoise1.par + +apnoise.par + +apnoise.key + +doc/apnoise.hlp + +apextract.x +t_apall.x +x_apextract.x +apextract.hd +apextract.men +apextract.cl +mkpkg + A new task for computing the noise sigma as a function of data value + was added. This allows checking the noise model parameter and + can be used as a diagnostic of the profile modeling. (8/28/93, Valdes) + +apfit.x +apextract.x + There were some additional problems with gain parameter dependencies + in the difference, fit, and normalization output functions. + (8/27/93, Valdes) + +apgetdata.x +aptrace.x +apedit.par +apfind.par +apfit.par +apflatten.par +apmask.par +apnormalize.par +aprecenter.par +apresize.par +apscatter.par +apsum.par +aptrace.par +apall.par +apall.hlp +apedit.hlp +apfind.hlp +apflatten.hlp +apmask.hlp +apfit.hlp +apnormalize.hlp +aprecenter.hlp +apresize.hlp +apscatter.hlp +apsum.hlp +aptrace.hlp + The nsum parameter may be negative to select a median rather than + a sum of lines/columns. The parameter files had to be modified to + remove the minimum range limit and the help files modified to + document the new option. (8/10/93, Valdes) + +=========== +V2.10.3beta +=========== + +doc/apall.hlp +doc/apsum.hlp + The format parameter description was added. (6/24/93, Valdes) + +apfind.x +apfindnew.x + Removed the threshold in peak finding requiring peaks to be above zero. + This works with the change to center1d to allow finding of apertures + when the data is negative. (5/5/93, Valdes) + +apfit.x + Added CCDMEAN=1. to output image in the normalization, flattening routines. + (4/16/93, Valdes) + +apextract.par +*.par +apgetim.x + Moved the "dispaxis" parameter to a package paraemter. + (3/8/93, Valdes) + +approfile.x + The profile was not cleared when saturated pixels are found. This + could cause NaNs to get into the data with the result that + cvfit could produce garbage. + (3/4/93, Valdes) + +debug.par +apparams.par +apnorm1.par +apflat1.par +apfit1.par +apall1.par + 1. Changed the default "fit2d" polynomial parameters to polyorder=10, + polysep=0.95. + 2. Changed the default "niterate" from 2 to 5. + (3/3/93, Valdes) + +approfile.x +doc/approfiles.hlp + For the "fit1d" algorithm I doubled the order it uses to fit + parallel to the disperison. The order is still computed based + on the tilt of the spectrum and the order used for the tracing + but now that number is doubled. (2/26/93, Valdes) + +apscatter.x + Revised the algorithm to keep the cross-dispersion fits in memory + rather than writing them to disk as an image. This speeds things + up in the case of slow I/O. (2/23/93, Valdes) + +t_apall.x +apscatter.x + 1. The temporary file name was not being passed to apscatter by + t_apall resulting in use of the name ".imh" which is hidden. + 2. Increased the column buffering size from 512*100 to 500000. + (2/5/93, Valdes) + +apextract.x + imaccf was being used as a boolean when it should be an int. + (12/13/92, Valdes) + +debug.par + A DPAR parameter file for use with debugging. (1/12/92, Valdes) + +apmw.x +apextract.x + Rewrote this to allow extractions of an arbitrary number of apertures. + Previously this was limited by MWCS. The output format is now + EQUISPEC. (1/12/92, Valdes) + +aprecenter.x + This routine was incorrectly selecting the apertures to be used. + is_in_range (Memi[ranges], i) --> is_in_range (Memi[ranges], AP_ID(aps[i])) + (1/8/93, Valdes and Hill) + +doc/apbackground.hlp + In responding to a concern about the 'b' key showing a fit even though + the background type was "median" I added a paragraph explaining this. + (1/8/93, Valdes) + +t_apall.x + The dispersion smoothing was turned off in noninteractive mode regardless + of the task parameter. This has been fixed. + (12/8/92, Valdes) + +t_apall.x + Added error check for ap_plot. + (10/14/92, Valdes) + +apextract.x + 1. When the dispersion axis is 1 the data buffer may contain garbage + because of using a malloc and because not all of this buffer is + necessarily used. Later the multiplication by the gain can cause + an arithmetic exception. The mallocs were replaced by callocs. + 2. Added errchks for the impl[123]r routines. + (9/10/92, Valdes) + +mkpkg +apextract.x +apmw.x + + 1. Separated out the MWCS routines into another file. + 2. Added an apmw_saveim procedure to produce simple 1D format as is done + in the ONEDSPEC package. + (8/24/92, Valdes) + +apskyeval.x + When doing the fitted background variable roundoff among machines led + to using different background points and, hence, gave noticibly different + results. The background points are now rounded to the nearest 1000th of + a pixel which will produce the same background points on all machines. + (8/19/92, Valdes) + +apnorm1.x + Added missing t_nlost parameter. (8/10/92, Valdes) + +aptrace.x + There was an incorrect order in checking for failed traces which ends + up referencing uninitialized memory. This bug has been there for a + long time (V2.8-V2.10) but only showed up during testing on the + SGI port. (7/31/92, Valdes) + +The following set of changes concern the treatment of the background sample +regions and min/max fitting limits. There was also a change in ICFIT +to check the min/max fitting limits and increase them if the sample region +is extended beyond the initial fitting limits. + +-------- + +apdefault.x + Now calls AP_ICSET with the image limits rather than the aperture + limits as required by the change to that routine. (7/30/92, Valdes) + +apedit.x + 1. The default aperture is reset after a colon command just in case + one of the default aperture parameters has changed. This is + slightly inefficient but the alternative is a more complex + AP_COLON to determine if a parameter relates to the default + aperture. + 2. Now calls AP_ICSET after fitting to apply the constraint that the + fitting limits pass under the aperture. (7/30/92, Valdes) + +apicset.x + 1. The input background limits for a new aperture (called + by AP_DEFAULT) are now the maximum limits defined by the image size + rather than the minimum limits defined by the aperture. + 2. If a null default sample is given it is mapped to "*". + 3. A sample with "*" will map to the maximum limits. + 4. Allow the input and output pointers to be the same in order + for the constraint that the fitting region pass under the + aperture can be applied. (7/30/92, Valdes) + +-------- + +doc/apall.hlp doc/apsum.hlp doc/apbackground.hlp + The documentation of the "median" and "minimum" options for the + background parameter needed to be added. (7/14/92, Valdes) + +apextract.x + The profile array needed to be corrected for the gain. This makes a + difference for the output formats that use the fitted profile + (tasks APFLATTEN, APFIT: formats fit, ratio, diff, flat). + (7/9/92, Valdes) + +apfit1.par + Was missing t_nlost. (7/9/92, Valdes) + +apparams.par +apnorm1.par +apflat1.par +apfit1.par +apall1.par + Replace prompt pfiT with pfit as it should be. (7/9/92, Valdes) + +======= +V2.10.2 +======= + +apextract.x + The WCS for the 3D images was changed to produce a WCSDIM of 3. + (6/30/92, Valdes) + +======= +V2.10.1 +======= + +======= +V2.10.0 +======= + +apextract.x + 1. The axis array which was set by a data statement was actually + modified in the routine causing an improper WCS type to be + set. + 2. If no coordinate label and/or units are found they are now set based + on DC-FLAG. Before calibrated long slit spectra ended up with the + right wavelength coordinates but a label of Pixel and no units. + (5/20/92, Valdes) + +apall1.par +apparams.par +apfit1.par +apflat1.par +apnorm1.par + The e_profile prompt contained a new line. This was removed. + (5/18/92, Valdes) + +doc/apexv210.ms + +doc/revisions.v3.ms - + Revisions summary document. (5/11/92, Valdes) + +apcolon.x +apedit.key +doc/apedit.hlp + Added t_nlost to the list of colon commands. (5/11/92, Valdes) + +apgetim.x + Added the qp and pl extensions to those stripped. (5/8/92, Valdes) + +apextract.x + Added error checking such that if there is a problem with reading the + input image WCS and warning is printed and pixel coordinates are set + in the output image. (5/8/92, Valdes) + +===== +V2.10 +===== + +apextract.x + For a single aperture using MULTISPEC WCS a dummy axis mapping was added + to make the image appear to be the first line of a parent 2D image. + (4/27/92, Valdes) + +approfile.x + Added a maximum order for the aphorne fitting function. (4/24/92, Valdes) + +apextract.x + Added a error check trap to clean up and free memory in case of an + error. (4/24/92, Valdes) + +t_apall.x +apdb.x +apedit.x +apcolon.x +apfind.x +apfindnew.x +apertures.h + Made the number of apertures dynamic. There is no longer a maximum + number of apertures allowed. (3/18/92, Valdes) + +t_apall.x + Length of format string declared as SZ_FNAME but used as SZ_LINE. + Change declaration to SZ_LINE. (3/12/92, MJF) + +apextract.x + Now the output extension is added only if the output name is the + same as the input name. Thus, if someone used <image>.ms as an + output name they won't get <image>.ms.ms. (2/12/92, Valdes) + +apvariance.x +apskyeval.x +approfile.x +apextract.x +appars.x + Trapped errors from getting the read noise and gain from the image header + to produce a meaningful warning message. (2/10/92, Valdes) + +apedit.x +apfind.x +t_apall.x +apids.x + 1. Added code to ignore negative beam numbers during extraction. + 2. Negative beam numbers are only generated if an explicit assignment + is made in the aperture id table or with 'j'; i.e. beam numbers + generated by adding or subtracting will not have a negative beam. + (2/10/92, Valdes) + +apids.x +apedit.x + Modified to not allow apertures numbers < 1. (1/22/92, Valdes) + +t_apall.x +x_apextract.x + Added new entry point, apslitproc, for the slit processing tasks. + (1/15/92, Valdes) + +apfind.x +apall.par +apfind.par + If nfind < 0 then the specified number of evenly spaced apertures are + defined. (1/14/92, Valdes) + +apextract.x +apsum.par +apnormalize.par +apflatten.par +apfit.par +apall.par +apparams.par +apnorm1.par +apflat1.par +apfit1.par +apall1.par +doc/apsum.hlp +doc/approfiles.hlp +doc/apnormalize.hlp +doc/apflatten.hlp +doc/apfit.hlp +doc/apall.hlp + 1. Replaced the "maxtilt" criteria for choosing the profile fitting + algorithm with an explicit "pfit" parameter. + 2. The parameter files were modified to remove "maxtilt", add + "pfit", and change the default "polyorder" parameter for the + fit2d algorithm from 4 to 6. + 3. The "pfit" parameter is redirected from the hidden parameter files + to the user parameter files allowing the users to select the profile + fitting algorithm. + (1/8/92, Valdes) + +t_apall.x +apdb.x + 1. Added special strings for the reference parameter. If the reference + parameter is "OLD" then only input images with existing database + entries are processed. If the reference is "NEW" then only input + images without existing databse entries are processed. + 2. Added a new procedure, ap_dbaccess, to simply check for the presence + of a database file. This is used for the above change. + (1/2/92, Valdes) + +aptrace.x +apall.par +aptrace.par +apparams.par +apall1.par +doc/apall.hlp +doc/aptrace.hlp + A new parameter has been added to set the number of steps which may + be lost during tracing. (9/5/91, Valdes) + +apextract.x + Changed ap_setdisp to ap_wcs. This routine uses MWCS and sets the + WCS to multispec. (8/29/91, Valdes) + +apextract.x + Modified so that profile image is used in place of input image for + determining the profile and eliminated the use of a disk profile file. + This is inefficient if the same profile image is used for many input + images but it is much easier for the user to understand. + (8/27/91, Valdes) + +apvariance.x + The subaperture extraction did not work because of a typo. + (8/27/91, Valdes) + +apextract.x + The profile image capability had several bugs which were fixed. + (8/27/91, Valdes) + +approfile.x + Fixed another division by zero problem in ap_horne. (8/27/91, Valdes) + +approfile.x + Failed to clear profile in the case the spectrum was negative. + (5/30/91, Valdes) + +apertures.h + Increased the maximum number of aperture from 100 to 1000. + (4/29/91, Valdes) + +apdefault.x +apicset.x + The default aperture was setting the background fitting range to + the full image range rather than range covered by the sample region. + This could cause singular solution errors in some cases. + (3/27/91, Valdes) + +apfind.x + Allowed still finding the specified number if some apertures (up to + 2) fail for some reason such as too near the edge. This is done by + setting the number of candidates to nfind+2. (3/26/91, Valdes) + +aprecenter.x +doc/aprecenter.hlp + When using the shift option the shift is now the median (including + averaging of central 2 shifts for even number of peaks) instead of + the average. (3/26/91, Valdes) + +appars.x +apall1.par +apfit1.par +apflat1.par +apnorm1.par +apparams.par + In order to allow writing to redirected parameters rather than overwrite + the redirection string a kluge was added using the prompt string. + The apput procedures check the prompt string for the first character + ">" and if present write to the parameter given in the rest of the + string. All the hidden parameter files with redirected parameters + had to be changes. (3/26/91, Valdes) + +apextract.par +apall.par apall1.par +apsum.par apdefault.par apparams.par +apfit.par apfit1.par +apflatten.par apflatten1.par +apnormalize.par apnorm1.par + 1. Moved format parameter from package parameters to + APALL and APSUM. + 2. Moved dispaxis parameter from package parameters to APDEFAULT. + 3. Added new background types. + (3/21/91, Valdes) + +t_apall.x + Allow scattered light correction to be run by APSCRIPT. + (3/21/91, Valdes) + +apscatter.x + Moved CLIO call for anssmooth out of loop to a single call using a + procedure variable. + (3/21/91, Valdes) + +apextract.x +apskyeval.x + Aded new background functions median and minimum. + (3/21/91, Valdes) + +================================= +V3 of APEXTRACT Installed 8/23/90 +================================= + +apextract$exsum.x + Added a test for the existence of output images before extractions and + a query to select whether to clobber spectra or not. (8/9/89, Valdes) + +apextract$exmvsum.x +apextract$exfit.x + 1. The moving average for profile images did not work correctly. It + subtracted the line moving out of the moving average but failed to + add in the line moving into the average. This caused the profile + to depart more and more from the data as the extraction procedes + through the image. + 2. The moving average for profile images actually used naverage + 1 + instead of naverage becuase in this case the line being extract is + also included in the average. + 3. The fitting of the model to the data had a funny behavior when the + model had negative values and variance weight was used. The + negative values are now excluded from the fitting calculation in + this case. Note that the model is supposed to not contain negative + values. Also note that if variance weighting is not used then the + negative values are used in straight least-squares fitting. + (8/8/89, Valdes) + +apextract$apicset.x +apextract$apedit.x +apextract$apupdate.x + The region over which the background fitting is defined has been extended + to require overlapping the aperture. (7/31/89, Valdes) + +apextract$apcolon.x + Added gdeactivate/greactivate calls when using EPARAM. (6/14/89, Valdes) + +apextract$apextract.x + If reference apertures are used without change (no recenter, edit, or + retrace) then the apertures were not written to the database. This has + been changed to write (or query if interactive) the apertures if + dbwrite=yes. (5/19/89, Valdes) + +apextract$exio.h +apextract$exio.x +apextract$exsum.x + 1. The maximum number of simultaneous extractions was increased from + 20 to 50. + 2. The amount of buffering used for column access (dispaxis=1) was + increased from 100K pixels to 1M chars. (5/12/89, Valdes) + +apextract$doc/apsum.hlp + Added a sentence about the proper alignment of echelle spectra. + (5/8/89, Valdes) + +apextract$t_apscatter.x + +apextract$apscatter.par + +apextract$apscat1.par + +apextract$apscat2.par + +apextract$doc/apscatter.hlp + +apextract$mkpkg +apextract$x_apextract.x +apextract$apextract.cl +apextract$apextract.men +apextract$apextract.hd +imred$echelle/apscatter.par + +imred$echelle/apscat1.par + +imred$echelle/apscat2.par + +imred$echelle/echelle.cl +imred$echelle/echelle.men + Added a new task, APSCATTER, to fit and subtract scattered light. + It includes two hidden psets, APSCAT1 and APSCAT2. (3/3/89, Valdes) + +apextract$apnormalize.par +imred$echelle/apnormalize.par + Input image parameter name needed to be changed from "images" to "input". + (2/28/89, Valdes) + +apextract$exio.x + Added errchk for imgeti related to getting DISPAXIS keyword which + might be missing. (2/28/89, Valdes) + +apextract$exsum.x + Changed usage of CRPIX keyword to real from integer. (1/25/89, Valdes) + +apextract$apgmark.x + The size of the aperture labels now decreases with increasing number + of apertures. (1/24/89, Valdes) + +apextract$t_apnorm.x +apextract$apnormalize.par +imred$echelle/apnormalize.par +apextract$doc/apnormalize.hlp + Changed parameter names "lowreject" to "low_reject" and "highreject" + to "high_reject" to be consistent with other ICFIT tasks. + (1/24/89, Valdes) + +apextract$aprecenter.x + The progress information was not using the verbose parameter. + (1/23/89, Valdes) + +apextract$apedit.x + Fixed bug causing 'i' info to only be visibly momentarily. + (12/16/88 Valdes) + +apextract$t_apnorm.x + When fitting the normalization spectrum interactively any deleted + points would be remembered in the following apertures. Deleted points + are now cleared after interactive fitting. (12/15/88 Valdes) + +apextract$apedit.x + Fixed a minor bug in the 's' option (center + wx --> wx) (12/15/88 Valdes) + +apextract$*.x +apextract$apio.par +apextract$doc/apio.hlp + Removed the beep option. (12/8/88 Valdes) + +apextract$exgmodaps.x + The temporary apertures array and number of apertures were not being + initialized correctly causing a segmentation violation every time + the program was run. Added an n = 0 statement and initialized all the + pointers to NULL. (10/13/88 Davis) + +apextract$exmvsum.x + When cleaning and using a moving average the replacement of the bad pixel + in a data profile back in the moving average was in error leading to + bad results and possible memory corruption. (10/9/88 Valdes) + +apextract$exfit.x +apextract$exmvsum.x + 1. The sigma clipping test now uses the variance relation for testing the + residuals. + 2. A bug was causing the length of the profile image to be incorrectly + referenced leading to an out of bounds error. + +apextract$apedit.x +apextract$exapsum.x + 1. After doing a ":line" new apertures were defined with the old line + as the aperture center. This made tracing fail. + Now after changing the line the default aperture is updated and + the apeture center is explicitly set every time. + 2. In a rare circumstance a divide by zero error occured for the fitted + background. This is now checked. (7/19/88 Valdes) + +noao$lib/scr/apedit.key +apextract$apedit.x + 1. Deleted a reference to :nfind in the cursor help. + 2. After deleting a background defintion it was no longer possible + to define a new one. Now an attempt to define backgrounds + after they have been deleted is initialized to the default again. + (7/1/88 Valdes) + +apextract$exsum.x + Fixed a bug in blocking overwriting of existing echelle format spectra. + Fixed a minor bug in writing the aperture info to the header of a 1D + format sky spectrum. (6/16/88 Valdes) + +apextract$apgmark.x + Labels are not written outside of graph range. (5/20/88 Valdes) + +apextract$apedit.x +apextract$exgraph.x +noao$lib/scr/apedit.key + Added 'I' interrupt. (4/20/88 Valdes) + +apextract$exio.x + EX_UNMAP when using column access was free a buffer supplied by + IMIO causing a memory corruption error on VMS. (3/30/88) + +apextract$exgmodaps.x + Model apertures where not being match up correctly resulting in a + warning message. (3/22/88 Valdes) + +apextract$exsum.x +apextract$exstrip.x +apextract$exrecen.x + Added iferr statements for asifit. Without this the task crashed + when an aperture went off the edge. (3/10/88 Valdes) + +apextract$* Major changes: + o Use profile template image + o Don't interpolate data profile before cleaning + o New background option + o Integrate apertures + o Restructure code + o And much more + (3/1/88 Valdes) + +============== +APEXTRACT V2.0 +============== + +apextract$excextract.x - +apextract$exlextract.x - + Removed these unused procedures. (1/5/88 Valdes) + +apextract$excstrip.x +apextract$exlstrip.x + Free curfit pointer if ic_fit returns an error. (1/5/88 Valdes) + +apextract$excsum.x +apextract$exlsum.x + Set background to zero if ic_fit returns an error. (1/5/88 Valdes) + + Original: + iferr (call ic_fit (AP_IC(aps[i]), cv, Memr[x], + Memr[bufin], Memr[w], ncols, YES, YES, YES, YES)) + ; + + New: + iferr { + call ic_fit (AP_IC(aps[i]), cv, Memr[x], + Memr[bufin], Memr[w], ncols, YES, YES, YES, YES) + call ex_apbkg (cv, ncols, center, low, high, + skyout[line,i]) + } then + skyout[line,i] = 0. + +apextract$exapsum.x + Added check for no data in sum. (1/5/88 Valdes) + + In procedure ex_apsum: + a = max (0.5, center + lower) + b = min (npts + 0.5, center + upper) + + if (a >= b) { <-- ADD + sum = 0. <-- ADD + return <-- ADD + } + + In procedure ex_apbkg: + a = max (0.5, center + lower) + b = min (npts + 0.5, center + upper) + + if (a >= b) { <-- ADD + bkg = 0. <-- ADD + return <-- ADD + } + +apextract$apnormalize.x + There was no error checking on ap_dbread which caused misleading errors + (apio package not found). This was fixed by updating the logic to be the + same as in apextract.x. A quick fix for outside sites is to add an + errchk for ap_dbread. (12/18/87 Valdes) + +apextract$apedit.x +apextract$apgscur.x + When first entering APEDIT with apertures defined the first attempt to + point the cursur at the first aperture uses an indefinite y value since + no cursor read has yet taken place. The choices are to set it to some + arbitrary value, some percentage level on screen, or do nothing. I + chose to do nothing. Thus, the cursor will not point at the current + aperture in this case but it will leave the cursor position unchanged. + (12/17/87 Valdes) + +apextract$apio.par +apextract$exsum.x +apextract$exoutsum.x +apextract$apedit.x + Added new parameter "format" to APIO pset. Added new output formats for + echelle and multispectra data consisting of a single 2D image. Added new + information in header. Old format is called "onedspec". + + Removed debugging print statement. When it was put in I don't know. + (12/17/87 Valdes) + +apextract$apextract.x + An error was introduced with the change of 11/9/87 such that the error + when a database file does not exists was no longer being trapped. This + was intended for reference images but was not intended for creating new + database files. An iferr was added. + +apextract$t_apnormalize.x +apextract$trtrace.x +apextract$exstrip.x +apextract$exsum.x + ERRCHK declarations for IMGETI were added to detect a missing DISPAXIS. + Failing to catch this error caused misleading error messages and + other fatal errors. (11/9/87 Valdes) + +apextract$apextract.x +apextract$apdb.x + An error reading apertures for a specified reference image is now + printed instead of assuming there are no reference apertures. + (11/9/87 Valdes) + +apextract$exfit.x + Changed the variance formula from + V = v0 + v1 * abs (S + B) + to + V = v0 + v1 * max (0, S + B) if v0 > 0 + V = v1 * max (1, S + B) if v0 = 0 + (11/9/87 Valdes; see also 8/6/87) + +apextract$t_apnormalize.x + When normalizing more than 20 apertures some of the apertures + were being lost in the output image. This was fixed to only + fill between the apertures on the first set of apertures. + + Normalizing when DISPAXIS=1 did not work. There were a number of + errors. This task was never tested with data in this orientation. + (9/22/87 Valdes) + +apextract$exfit.x +apextract$apsum.par +apextract$apstrip.par +apextract$doc/apsum.hlp +apextract$doc/apstrip.hlp + When computing the variance for doing variance weighting the + intensity could be negative. An absolute value was added to + correct this. + + Make defaults for naverage=100 and nclean=2 because people have + been using inadequate number of lines for low signal-to-noise + data and because of interpolation even an 1 pixel cosmic ray + expands to two pixels. (8/6/87 Valdes) + +==== +V2.5 +==== + +apextract$apio.par +apextract$apio.x +apextract$t_apnormalize.x +apextract$exsum.x +apextract$exstrip.x +apextract$apfindnew.x +apextract$apfind.x +apextract$apextract.x +apextract$apedit.x +apextract$trtrace.x +apextract$trltrace.x +apextract$trctrace.x +apextract$exgraph.x +apextract$doc/apio.hlp + Valdes, May 19, 1987 + 1. Added the parameter "verbose" to the APIO pset to allow turning off + log information to the terminal. + 2. Made changes to minimize switching between text and graphics mode. + With verbose=no there should be essentially no mode switching. This + was done for terminals in which such switches is either annoying + or slow. + +apextract$mkpkg +apextract$apcvset.x +apextract$t_apnormalize.x +apextract$trtrace.x +apextract$exsum.x +apextract$exstrip.x +apextract$apgetdata.x +apextract$apimmap.x + + Valdes, April 24, 1987 + 1. Protection against using an image which is not 2 dimensional was added. + +apextract$apedit.x +apextract$apextract.x +apextract$apsum.par +apextract$exapsum.x +apextract$excsum.x +apextract$exgprofs.x +apextract$exlsum.x +apextract$exoutsum.x +apextract$exsum.x +apextract$doc/apsum.hlp + Valdes, April 11, 1987 + 1. Added additional option to APSUM to output the subtracted sky + background spectra when doing background subtraction. + +apextract$apextract.hd +apextract$apextract.men +apextract$apextract.par +apextract$apgetim.x +apextract$apnormalize.par +apextract$mkpkg +apextract$t_apnormalize.x + +apextract$x_apextract.x +apextract$doc/apnormalize.hlp + + Valdes, April 3, 1987 + 1. New task APNORMALIZE installed. + +apextract$*x + Valdes, February 17, 1987 + 1. Required GIO changes. + +apextract$apio.h +apextract$exgraph.x +apextract$apio.x +apextract$excextract.x +apextract$apextract.tar +apextract$trltrace.x +apextract$trctrace.x +apextract$exlextract.x +apextract$applot.x +apextract$apedit.x + Valdes, February 13, 1987 + 1. I've made a number of modifications to the APEXTRACT package to + correct problems in the way graphics and text are mixed. The + main change was to make the graphics open very local to the + procedure doing the graphics. Previously the graphics device + was opened at the beginning of the logical task and remained + open until the end. This was done since the integrated nature + of the package has many procedures which may do graphics. This + has the bad side effects that for the first graphics open of + the process the terminal enters graphics mode (graphics screen + on SUN and clear screen on VT640) well before any graphics is + performed and text I/O is a problem. Putting GOPEN and GCLOSE + immediately around the code that does graphics fixed almost all + the problems. The only time that text output is now done when + the graphics terminal is open is for '?' and ':show' type of + commands. The only remaining problem is the page wait problem + associated with '?' occuring before a cursor read rather than + immediately after the text output causing the last written + status line to become confused with the page wait prompt. + +apextract$apfind.par + Valdes, February 12, 1987 + 1. The parameter apfind.nfind was changed back to hidden in order + for apsum to work in the background. Note the PSET mechanism + would fix this by allowing nfind to be specified on the command + line. + +apextract$apio.par + Valdes, February 9, 1987 + 1. New users rarely look at or know about the log files produced by + the package tasks. These files (particularly graphics) take up + a lot of space. Therefore the default is now not to log + text or graphics output. + +apextract$apedit.x +apextract$apsort.x +apextract$exapsum.x +apextract$trltrace.x +apextract$trctrace.x +apextract$doc/apedit.hlp +noao$lib/scr/apedit.key + Valdes, February 2, 1987 + 1. Added a new edit option, 'o', to reorder the aperture id and beam + numbers sequentially. This is useful after apertures have been + deleted and added interactively. + 2. If the aperture went completely off the image (ie there is no + overlap of even part of the aperture with the image) a random value + was given the aperture sum because the value was not intialize to + zero. It is now initialize to zero. + 3. There is now a requirement that more than three points be traced + before a trace will be fit. + +apextract$trltrace.x +apextract$trctrace.x +apextract$apgetdata.x + Valdes, January 30, 1987 + 1. The middle line (default) was not calculated correctly. + 2. The tracing would sometimes run beyond the end of the image. The + value of this traced point is suspect. It was found because there + would be a point off the end of the ICFIT graph which was set to + be the size of the image. + 3. Just in case a traced point is right at the edge I made the default + window for fitting the trace extend half a step beyond the edges + of the image. + +apextract$exsum.x +apextract$exstrip.x + Valdes, January 30, 1987 + 1. Skip Schaller (Steward) reported a problem with running out of memory + with an input list of 20 images. Also when the user deleted input + images after they were processed but before the list was finished + (to reduce memory) the memory was not actually freed until the process + actually finished. I found that the input images + where not being closed! (Sorry about this really stupid error.) + This may not be all the problem but it is probable since IMIO + maintains large buffers. + +apextract$apcolon.x + Valdes, January 15, 1987 + 1. Replaced dictionary string and numeric case by macros for readability. + +apextract$apfind.par + Valdes, December 19, 1986 + 1. Change the default NFIND parameter in APFIND to auto mode. + +apextract$apnearest.x + Valdes, December 12, 1986 + 1. It is possible for more than one aperture to be equidistant from + the cursor, particularly when more than one aperture is defined for + the same feature. This is ambiguous for those commands which operate on + the nearest aperture. The modification will query the user if it + is found that there is more than one aperture at the same distance + from the cursor. + +apextract$peaks.x + Valdes, October 10, 1986 + 1. VMS adjustable array dimension error found. Replaced declaration + dimension by ARB since the passed dimension value may be zero. + +apextract$* + Valdes, September 16, 1986 + 1. A new version of the package has been installed. It is very + different from the old version. The user parameter files must + be unlearned. + +==================== +New Package Released +==================== + +apextract$: Valdes, July 19, 1986 + 1. APEDIT and TRACE modified to include a detection threshold parameter + for profile centering. + 2. The help pages were updated. + +apextract$apedit.x, apvalue.x: Valdes, July 17, 1986 + 1. A bug was found that appears if you edit the apertures of a + previously traced image. The center moves with use of 'l' or + 'u'. This is due to an inconsistency between whether the aperture + center is before or after the traced shift is added. Changes + to APVALUE.X and the calls to it in APEDIT.X fix this. + +apextract$: Valdes, July 15, 1986 + 1. TRACE had a bug when trying to specify an explicit starting + line to edit and trace from. This was fixed. + 2. EXCEXTRACT.X, EXLEXTRACT.X, and EXGPROFS.X were modified to + check for errors from background fitting. This arose when + trying to get the background for a spectrum which has gone + off the edge of the image. + +apextract$apedit.x, apsort.x : Valdes, July 9, 1986 + 1. When changing the aperture number the apertures are sorted and + then the wrong aperture could become the current aperture if + another aperture exists with the same aperture number. This was + fixed so that the sorting returns the correct current aperture + after sorting. Also apindex.x is no longer needed. + +apextract$apedit.x: Valdes, July 7, 1986 + 1. The 'd' delete key now does nothing if no apertures are defined. + Previously it would cause a failure of the task. + +apextract$apedit.x: Valdes, July 7, 1986 + 1. Added redraw and window commands. + 2. Help page and '?' menu updated. + +apextract$apedit.x: Valdes, July 3, 1986 + 1. APEDIT modified to use new ICFIT package. + +apextract$apgetim.x: Valdes, July 1, 1986 + 1. New procedure to strip the image extension. This is necessary + to create proper database files and to avoid having two legal + names for images in the database. + +apextract$exapstrip.x: Valdes, July 1, 1986 + 1. Simple strip extraction without profile modeling interpolated + the data so that the lower edge of the aperture was centered + on the first pixel. This is inconsistent with the other extractions + which put the center of the aperture at the center of a pixel. + This has been fixed. + +apextract: Valdes, June 30, 1986: + 1. TRACE was not correctly initializing the new ICFIT package. + In particular the task parameters "function" and "order" had no + effect and when multiple files were used the last set parameters + were not retained. Changes to t_trace.x, trctrace.x, trltrace.x. + +===================================== +STScI Pre-release and SUN 2.3 Release +===================================== + +apextract: Valdes, June 20, 1986: + 1. New APEXTRACT installed. This version includes background + subtraction and new ICFIT. + +apextract: Valdes, June 2, 1986 + 1. Another round of name changes. EDITAPS -> APEDIT, + EXTRACT1 -> SUMEXTRACT, EXTRACT2 -> STRIPEXTRACT. + +apextract: Valdes, May 16, 1986 + 1. Renamed APDEFINE to EDITAPS. + 2. Moved parameters used in editing the apertures from EXTRACT1 and + EXTRACT2. These are now obtained from EDITAPS regardless of which + task calls apedit. + 3. Added parameters "cradius", "cwidth", "ctype", "lower", and "upper" + to EDITAPS. The first parameters control profile centering and the + last parameters set the default aperture limits. + 1. Added new keys. 'c' center current aperture of profile near the cursor. + 'm' mark and center aperture on profile near the cursor. 's' shift + the center of the current aperture to the cursor position. The change + allows centering of profiles using CENTER1D. + +apextract$extract.x: Valdes, May 13, 1986 + 1. EXTRACT has been broken up into two tasks; EXTRACT1 and EXTRACT2. + EXTRACT1 extracts weighted summed 1D spectra. EXTRACT2 extracts + 2D apertures corrected for shifts across the dispersion. + +apextract: Valdes, April 23, 1986 + 1. Modified EXTRACT to only warn about an existing output image. + This allows adding a new aperture without needing to delete + old apertures or reextract previous extractions. + +apextract: Valdes, April 21, 1986 + 1. All procedures which pass the number of current apertures as an + argument and then dimension the array with this number + were modified by dimensioning the array as dimension + APS_MAXAPS or ARB. This was done because the number of apertures + might be zero. This is a fatal error on VMS/VAX though not on UNIX/VAX. + +apextract: Valdes, March 27, 1986 + 1. Modified EXTRACT (exsum.x and exwt.x) to update the dispersion image + header parameters. In particular if the input dispersion axis is 2 + then the header parameters must be reset to dispersion axis 1. + +=========== +Release 2.2 +=========== +.endhelp diff --git a/noao/twodspec/apextract/apall.par b/noao/twodspec/apextract/apall.par new file mode 100644 index 00000000..7c97a920 --- /dev/null +++ b/noao/twodspec/apextract/apall.par @@ -0,0 +1,96 @@ +# APALL + +input,s,a,,,,List of input images +output,s,h,"",,,List of output spectra +apertures,s,h,"",,,Apertures +format,s,h,"multispec","onedspec|multispec|echelle|strip",,Extracted spectra format +references,s,h,"",,,List of aperture reference images +profiles,s,h,"",,,"List of aperture profile images +" +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,yes,,,Recenter apertures? +resize,b,h,yes,,,Resize apertures? +edit,b,h,yes,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,Fit the traced points interactively? +extract,b,h,yes,,,Extract spectra? +extras,b,h,yes,,,"Extract sky, sigma, etc.?" +review,b,h,yes,,,"Review extractions? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,10,,,"Number of dispersion lines to sum or median + +# DEFAULT APERTURE PARAMETERS +" +lower,r,h,-5,,,Lower aperture limit relative to center +upper,r,h,5,,,Upper aperture limit relative to center +apidtable,s,h,"",,,"Aperture ID table (optional) + +# DEFAULT BACKGROUND PARAMETERS +" +b_function,s,h,"chebyshev","chebyshev|legendre|spline1|spline3",,Background function +b_order,i,h,1,1,,Background function order +b_sample,s,h,"-10:-6,6:10",,,Background sample regions +b_naverage,i,h,-3,,,Background average or median +b_niterate,i,h,0,0,,Background rejection iterations +b_low_reject,r,h,3.,0.,,Background lower rejection sigma +b_high_reject,r,h,3.,0.,,Background upper rejection sigma +b_grow,r,h,0.,0.,,"Background rejection growing radius + +# APERTURE CENTERING PARAMETERS +" +width,r,h,5.,0.,,Profile centering width +radius,r,h,10.,,,Profile centering radius +threshold,r,h,0.,0.,,"Detection threshold for profile centering + +# AUTOMATIC FINDING AND ORDERING PARAMETERS +" +nfind,i,q,,,,Number of apertures to be found automatically +minsep,r,h,5.,1.,,Minimum separation between spectra +maxsep,r,h,100000.,1.,,Maximum separation between spectra +order,s,h,"increasing","increasing|decreasing",,"Order of apertures + +# RECENTERING PARAMETERS +" +aprecenter,s,h,"",,,Apertures for recentering calculation +npeaks,r,h,INDEF,0.,,Select brightest peaks +shift,b,h,yes,,,"Use average shift instead of recentering? + +# RESIZING PARAMETERS +" +llimit,r,h,INDEF,,,Lower aperture limit relative to center +ulimit,r,h,INDEF,,,Upper aperture limit relative to center +ylevel,r,h,0.1,,,Fraction of peak or intensity for automatic width +peak,b,h,yes,,,Is ylevel a fraction of the peak? +bkg,b,h,yes,,,"Subtract background in automatic width?" +r_grow,r,h,0.,,,"Grow limits by this factor" +avglimits,b,h,no,,,"Average limits over all apertures? + +# TRACING PARAMETERS +" +t_nsum,i,h,10,1,,Number of dispersion lines to sum +t_step,i,h,10,1,,Tracing step +t_nlost,i,h,3,1,,Number of consecutive times profile is lost before quitting +t_function,s,h,"legendre","chebyshev|legendre|spline1|spline3",,Trace fitting function +t_order,i,h,2,1,,Trace fitting function order +t_sample,s,h,"*",,,Trace sample regions +t_naverage,i,h,1,,,Trace average or median +t_niterate,i,h,0,0,,Trace rejection iterations +t_low_reject,r,h,3.,0.,,Trace lower rejection sigma +t_high_reject,r,h,3.,0.,,Trace upper rejection sigma +t_grow,r,h,0.,0.,,"Trace rejection growing radius + +# EXTRACTION PARAMETERS +" +background,s,h,"none","none|average|median|minimum|fit",,Background to subtract +skybox,i,h,1,1,,Box car smoothing length for sky +weights,s,h,"none","none|variance",,Extraction weights (none|variance) +pfit,s,h,"fit1d","fit1d|fit2d",,Profile fitting type (fit1d|fit2d) +clean,b,h,no,,,Detect and replace bad pixels? +saturation,r,h,INDEF,1.,,Saturation level +readnoise,s,h,"0.",,,Read out noise sigma (photons) +gain,s,h,"1.",,,Photon gain (photons/data number) +lsigma,r,h,4,0,,Lower rejection threshold +usigma,r,h,4,0,,Upper rejection threshold +nsubaps,i,h,1,1,,Number of subapertures per aperture diff --git a/noao/twodspec/apextract/apall1.par b/noao/twodspec/apextract/apall1.par new file mode 100644 index 00000000..12a28b32 --- /dev/null +++ b/noao/twodspec/apextract/apall1.par @@ -0,0 +1,117 @@ +# OUTPUT PARAMETERS + +apertures,s,h,)apall.apertures,,,>apall.apertures +format,s,h,)apall.format,,,>apall.format +extras,b,h,)apall.extras,,,>apall.extras +dbwrite,s,h,yes,,,Write to database? +initialize,b,h,yes,,,Initialize answers? +verbose,b,h,)_.verbose,,,"Verbose output? + +# DEFAULT APERTURE PARAMETERS +" +lower,r,h,)apall.lower,,,>apall.lower +upper,r,h,)apall.upper,,,>apall.upper +apidtable,s,h,)apall.apidtable,,,">apall.apidtable + +# DEFAULT BACKGROUND PARAMETERS +" +b_function,s,h,)apall.b_function,,,>apall.b_function +b_order,i,h,)apall.b_order,,,>apall.b_order +b_sample,s,h,)apall.b_sample,,,>apall.b_sample +b_naverage,i,h,)apall.b_naverage,,,>apall.b_naverage +b_niterate,i,h,)apall.b_niterate,,,>apall.b_niterate +b_low_reject,r,h,)apall.b_low_reject,,,>apall.b_low_reject +b_high_reject,r,h,)apall.b_high_reject,,,>apall.b_high_reject +b_grow,r,h,)apall.b_grow,,,">apall.b_grow + +# APERTURE CENTERING PARAMETERS +" +width,r,h,)apall.width,,,>apall.width +radius,r,h,)apall.radius,,,>apall.radius +threshold,r,h,)apall.threshold,,,">apall.threshold + +# AUTOMATIC FINDING AND ORDERING PARAMETERS +" +nfind,i,h,)apall.nfind,,,>apall.nfind +minsep,r,h,)apall.minsep,,,>apall.minsep +maxsep,r,h,)apall.maxsep,,,>apall.maxsep +order,s,h,)apall.order,,,">apall.order + +# RECENTERING PARAMETERS +" +aprecenter,s,h,)apall.aprecenter,,,>apall.aprecenter +npeaks,r,h,)apall.npeaks,,,>apall.npeaks +shift,b,h,)apall.shift,,,">apall.shift + +# RESIZING PARAMETERS +" +llimit,r,h,)apall.llimit,,,>apall.llimit +ulimit,r,h,)apall.ulimit,,,>apall.ulimit +ylevel,r,h,)apall.ylevel,,,>apall.ylevel +peak,b,h,)apall.peak,,,>apall.peak +bkg,b,h,)apall.bkg,,,>apall.bkg +r_grow,r,h,)apall.r_grow,,,>apall.r_grow +avglimits,b,h,)apall.avglimits,,,">apall.avglimits + +# EDITING PARAMETERS +" +e_output,s,q,,,,Output spectra rootname +e_profiles,s,q,,,,Profile reference image + +# TRACING PARAMETERS +t_nsum,i,h,)apall.t_nsum,,,>apall.t_nsum +t_step,i,h,)apall.t_step,,,>apall.t_step +t_nlost,i,h,)apall.t_nlost,,,>apall.t_nlost +t_width,r,h,)apall.width,,,>apall.width +t_function,s,h,)apall.t_function,,,>apall.t_function +t_order,i,h,)apall.t_order,,,>apall.t_order +t_sample,s,h,)apall.t_sample,,,>apall.t_sample +t_naverage,i,h,)apall.t_naverage,,,>apall.t_naverage +t_niterate,i,h,)apall.t_niterate,,,>apall.t_niterate +t_low_reject,r,h,)apall.t_low_reject,,,>apall.t_low_reject +t_high_reject,r,h,)apall.t_high_reject,,,>apall.t_high_reject +t_grow,r,h,)apall.t_grow,,,">apall.t_grow + +# EXTRACTION PARAMETERS +" +background,s,h,)apall.background,,,>apall.background +skybox,i,h,)apall.skybox,,,>apall.skybox +weights,s,h,)apall.weights,,,>apall.weights +pfit,s,h,)apall.pfit,,,>apall.pfit +clean,b,h,)apall.clean,,,>apall.clean +nclean,r,h,0.5,,,Maximum number of pixels to clean +niterate,i,h,5,0,,Number of profile fitting iterations +saturation,r,h,)apall.saturation,,,>apall.saturation +readnoise,s,h,)apall.readnoise,,,>apall.readnoise +gain,s,h,)apall.gain,,,>apall.gain +lsigma,r,h,)apall.lsigma,,,>apall.lsigma +usigma,r,h,)apall.usigma,,,>apall.usigma +polysep,r,h,0.90,0.1,0.95,Marsh algorithm polynomial spacing +polyorder,i,h,10,1,,Marsh algorithm polynomial order +nsubaps,i,h,)apall.nsubaps,,,">apall.nsubaps + +# ANSWER PARAMETERS +" +ansclobber,s,h,"no",,," " +ansclobber1,s,h,"no",,," " +ansdbwrite,s,h,"yes",,," " +ansdbwrite1,s,h,"yes",,," " +ansedit,s,h,"yes",,," " +ansextract,s,h,"yes",,," " +ansfind,s,h,"yes",,," " +ansfit,s,h,"yes",,," " +ansfitscatter,s,h,"yes",,," " +ansfitsmooth,s,h,"yes",,," " +ansfitspec,s,h,"yes",,," " +ansfitspec1,s,h,"yes",,," " +ansfittrace,s,h,"yes",,," " +ansfittrace1,s,h,"yes",,," " +ansflat,s,h,"yes",,," " +ansnorm,s,h,"yes",,," " +ansrecenter,s,h,"yes",,," " +ansresize,s,h,"yes",,," " +ansreview,s,h,"yes",,," " +ansreview1,s,h,"yes",,," " +ansscat,s,h,"yes",,," " +anssmooth,s,h,"yes",,," " +anstrace,s,h,"yes",,," " diff --git a/noao/twodspec/apextract/apalloc.x b/noao/twodspec/apextract/apalloc.x new file mode 100644 index 00000000..086db650 --- /dev/null +++ b/noao/twodspec/apextract/apalloc.x @@ -0,0 +1,34 @@ +include "apertures.h" + +# AP_ALLOC -- Allocate and initialize an aperture structure. + +procedure ap_alloc (ap) + +pointer ap # Aperture + +begin + call calloc (ap, AP_LEN, TY_STRUCT) + AP_TITLE(ap) = NULL + AP_CV(ap) = NULL + AP_IC(ap) = NULL + AP_SELECT(ap) = YES +end + + +# AP_FREE -- Free an aperture structure and related CURFIT structures. + +procedure ap_free (ap) + +pointer ap # Aperture + +begin + if (ap != NULL) { + if (AP_TITLE(ap) != NULL) + call mfree (AP_TITLE(ap), TY_CHAR) + if (AP_CV(ap) != NULL) + call cvfree (AP_CV(ap)) + if (AP_IC(ap) != NULL) + call ic_closer (AP_IC(ap)) + call mfree (ap, TY_STRUCT) + } +end diff --git a/noao/twodspec/apextract/apanswer.x b/noao/twodspec/apextract/apanswer.x new file mode 100644 index 00000000..0077af4a --- /dev/null +++ b/noao/twodspec/apextract/apanswer.x @@ -0,0 +1,121 @@ +define ANSWERS "|no|yes|NO|YES|" + + +# AP_ANSWER -- Prompt the user (if needed) and return bool based +# on 4-valued response + +bool procedure ap_answer (param, prompt) + +char param[ARB] # Parameter name +char prompt[ARB] # Prompt to be issued + +char word[3] +int i, apgwrd() +pointer pmode + +begin + i = apgwrd (param, word, 3, ANSWERS) + switch (i) { + case 3: + return (false) + case 4: + return (true) + default: + call malloc (pmode, SZ_LINE, TY_CHAR) + call sprintf (Memc[pmode], SZ_LINE, "%s.p_mode") + call pargstr (param) + call appstr (Memc[pmode], "q") + repeat { + call eprintf (prompt) + call flush (STDERR) + ifnoerr (i = apgwrd (param, word, 3, ANSWERS)) + break + } + call appstr (param, word) + call appstr (Memc[pmode], "h") + call mfree (pmode, TY_CHAR) + } + + switch (i) { + case 1, 3: + return (false) + case 2, 4: + return (true) + } +end + + +# APGANSB -- Convert 4-valued parameter to bool + +bool procedure apgansb (param) + +char param[ARB] # Parameter name + +char word[3] +int apgwrd() + +begin + switch (apgwrd (param, word, 3, ANSWERS)) { + case 1, 3: + return (false) + default: + return (true) + } +end + + +# APGANS -- Convert 4-value parameter to bool except "no" is true. + +bool procedure apgans (param) + +char param[ARB] # Parameter name + +char word[3] +pointer pmode +bool streq() + +begin + call malloc (pmode, SZ_LINE, TY_CHAR) + call sprintf (Memc[pmode], SZ_LINE, "%s.p_mode") + call pargstr (param) + call apgstr (Memc[pmode], word, 3) + if (word[1] != 'h') + call appstr (Memc[pmode], "h") + call mfree (pmode, TY_CHAR) + call apgstr (param, word, 3) + return (!streq (word, "NO")) +end + + +# APPANS -- Put 4-valued parameter based on interactive parameter. + +procedure appans (param, ival, nival) + +char param[ARB] # Parameter +bool ival # Interactive value +bool nival # Noninteractive value + +char word[3] +pointer pmode +bool clgetb() + +begin + call malloc (pmode, SZ_LINE, TY_CHAR) + call sprintf (Memc[pmode], SZ_LINE, "%s.p_mode") + call pargstr (param) + call apgstr (Memc[pmode], word, 3) + if (word[1] != 'h') + call appstr (Memc[pmode], "h") + call mfree (pmode, TY_CHAR) + if (clgetb ("interactive")) { + if (ival) + call appstr (param, "yes") + else + call appstr (param, "NO") + } else { + if (nival) + call appstr (param, "YES") + else + call appstr (param, "NO") + } +end diff --git a/noao/twodspec/apextract/apcenter.x b/noao/twodspec/apextract/apcenter.x new file mode 100644 index 00000000..88f089d1 --- /dev/null +++ b/noao/twodspec/apextract/apcenter.x @@ -0,0 +1,26 @@ +include <pkg/center1d.h> + +# AP_CENTER -- Locate the center of an emission profile. This is done +# using the CENTER1D algorithm. The procedure gets the centering +# parameters using CL queries. If the center is not found because of the +# RADIUS or THRESHOLD centering criteria then INDEF is returned. + +real procedure ap_center (x, data, npts) + +real x # Initial guess +real data[npts] # Data +int npts # Number of data points + +real width # Centering width +real radius # Centering radius +real threshold # Detection threshold + +real apgetr(), center1d() + +begin + width = apgetr ("width") + radius = apgetr ("radius") + threshold = apgetr ("threshold") + + return (center1d (x, data, npts, width, EMISSION, radius, threshold)) +end diff --git a/noao/twodspec/apextract/apcolon.x b/noao/twodspec/apextract/apcolon.x new file mode 100644 index 00000000..9e910a95 --- /dev/null +++ b/noao/twodspec/apextract/apcolon.x @@ -0,0 +1,384 @@ +include <gset.h> +include <imhdr.h> +include <error.h> +include "apertures.h" + +# List of colon commands. +define CMDS "|show|parameters|database|logfile|plotfile|read|write|image\ + |line|nsum|center|lower|upper|title\ + |extras,b|apidtable,s|b_function,s|b_order,i|b_sample,s\ + |b_naverage,i|b_niterate,i|b_low_reject,r|b_high_reject,r|b_grow,r\ + |minsep,r|maxsep,r|order,s|apertures,s|npeaks,r|shift,b|llimit,r\ + |ulimit,r|ylevel,r|peak,b|bkg,b|r_grow,r|avglimits,b|width,r|radius,r\ + |threshold,r|t_nsum,i|t_step,i|t_width,r|t_function,s|t_order,i\ + |t_sample,s|t_naverage,i|t_niterate,i|t_low_reject,r|t_high_reject,r\ + |t_grow,r|nsubaps,i|background,s|skybox,i|clean,b|saturation,r\ + |weights,s|readnoise,s|gain,s|lsigma,r|usigma,r|t_nlost,i|" + +define SHOW 1 # Show apertures +define PARAMS 2 # Show parameters +define DATABASE 3 # Database +define LOGFILE 4 # Logfile +define PLOTFILE 5 # Plotfile +define READ 6 # Read aperture database entry +define WRITE 7 # Write aperture database entry +define IMAGE 8 # Image being edited +define LINE 9 # Set image line to display +define NSUM 10 # Set number of image lines to sum for display +define CENTER 11 # Set aperture center +define LOWER 12 # Set aperture lower limit +define UPPER 13 # Set aperture upper limit +define APTITLE 14 # Set aperture title + + +# AP_COLON -- Process colon commands. The colon commands may be abbreviated. +# Optional arguments determine either the output or the value of a parameter. +# Changes are signaled to the calling task with the flags NEWGRAPH, NEWIM, +# and NEWDATA. This task does CLIO including CLCMDW commands. + +procedure ap_colon (cmd, im, gp, apdef, aps, naps, current, image, line, + nsum, all, newgraph, newim, newdata, statline) + +char cmd[ARB] # Colon command +pointer im # IMIO pointer +pointer gp # GIO pointer +pointer apdef # Default aperture +pointer aps # Aperture pointers +int naps # Number of apertures +int current # Current aperture +char image[SZ_FNAME] # Image name +int line # Dispersion line +int nsum # Number of lines to sum +int all # All switch +int newgraph # New graph flag +int newim # New image flag +int newdata # New data flag +int statline # Status line used? + +bool bval +int i, j, ival, apid, apbeam +real center, low, high, rval +pointer sp, wrd, str + +bool strne(), apgetb() +real apgetr() +int nscan(), strdic(), imaccess(), apgeti(), stridxs() +errchk ap_apertures, ap_show, ap_params, ap_dbread, ap_dbwrite, ap_openio + +define done_ 99 + +begin + call smark (sp) + call salloc (wrd, SZ_LINE, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + + # Scan the command string for the first word which may be abbreviated. + call sscan (cmd) + call gargwrd (Memc[wrd], SZ_LINE) + i = strdic (Memc[wrd], Memc[wrd], SZ_LINE, CMDS) + if (i == 0) { + call printf ("Unrecognized or ambiguous command\007") + statline = YES + call sfree (sp) + return + } + j = stridxs (",", Memc[wrd]) + + if (j == 0) { + switch (i) { + case SHOW: # :show - Show aperture list + call gargwrd (cmd, SZ_LINE) + if (nscan() == 1) { + call gdeactivate (gp, AW_CLEAR) + call ap_show ("STDOUT", Memi[aps], naps) + call greactivate (gp, AW_PAUSE) + } else { + iferr (call ap_show (cmd, Memi[aps], naps)) { + call erract (EA_WARN) + statline = YES + } + } + case PARAMS: # :parameters - Show parameters + call gargwrd (cmd, SZ_LINE) + if (nscan() == 1) { + call mktemp ("junk", cmd, SZ_LINE) + iferr (call ap_params (cmd, image, line, nsum)) { + call gdeactivate (gp, AW_CLEAR) + call ap_params ("STDOUT", image, line, nsum) + call greactivate (gp, AW_PAUSE) + } else { + call gpagefile (gp, cmd, ":parameters") + call delete (cmd) + } + } else { + iferr (call ap_params (cmd, image, line, nsum)) { + call erract (EA_WARN) + statline = YES + } + } + case DATABASE: # :database - Database name + call gargwrd (cmd, SZ_LINE) + if (nscan() == 1) { + call clgstr ("database", cmd, SZ_LINE) + call printf ("database %s") + call pargstr (cmd) + statline = YES + } else + call clpstr ("database", cmd) + case LOGFILE: # :logfile - Logfile name + call gargwrd (cmd, SZ_LINE) + if (nscan() == 1) { + call clgstr ("logfile", cmd, SZ_LINE) + call printf ("logfile %s") + call pargstr (cmd) + statline = YES + } else + call clpstr ("logfile", cmd) + case PLOTFILE: # :plotfile - Plotfile name + call gargwrd (cmd, SZ_LINE) + if (nscan() == 1) { + call clgstr ("plotfile", cmd, SZ_LINE) + call printf ("plotfile %s") + call pargstr (cmd) + statline = YES + } else + call clpstr ("plotfile", cmd) + case READ: # :read - Read database entry + iferr { + call gargwrd (cmd, SZ_LINE) + if (nscan() == 1) + call ap_dbread (image, aps, naps) + else { + call xt_stripwhite (cmd) + if (cmd[1] == EOS) + call ap_dbread (image, aps, naps) + else { + call ap_dbread (cmd, aps, naps) + call appstr ("ansdbwrite1", "yes") + } + } + } then { + call erract (EA_WARN) + statline = YES + } + current = min (1, naps) + newgraph = YES + case WRITE: # :write - Write database entry + iferr { + call gargwrd (cmd, SZ_LINE) + if (nscan() == 1) + call ap_dbwrite (image, aps, naps) + else { + call xt_stripwhite (cmd) + if (cmd[1] == EOS) + call ap_dbwrite (image, aps, naps) + else { + call ap_dbwrite (cmd, aps, naps) + call appstr ("ansdbwrite1", "yes") + } + } + } then { + call erract (EA_WARN) + statline = YES + } + case IMAGE: # :image - Define a new image + call gargwrd (cmd, SZ_LINE) + if (nscan() == 1) { + call printf ("image %s") + call pargstr (image) + statline = YES + } else { + call xt_stripwhite (cmd) + if ((cmd[1] != EOS) && (strne (cmd, image))) { + if (imaccess (cmd, READ_ONLY) == YES) + newim = YES + else { + call eprintf ( + "WARNING: Can't read image %s") + call pargstr (cmd) + statline = YES + } + } + } + case LINE: # :line - Image line or column + call gargi (ival) + if (nscan() < 2) { + call printf ("line %d") + call pargi (line) + statline = YES + } else if (ival != line) { + call strcpy (image, cmd, SZ_LINE) + line = ival + newdata = YES + } + case NSUM: # :nsum - Number of image lines or columns to sum + call gargi (ival) + if (nscan() < 2) { + call printf ("nsum %d") + call pargi (nsum) + statline = YES + } else if (ival != nsum) { + call strcpy (image, cmd, SZ_LINE) + nsum = ival + newdata = YES + } + case CENTER: # :center - Set aperture center + if (current == 0) + goto done_ + call gargr (rval) + if (nscan() == 1) { + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + call printf ("center %g") + call pargr (center) + statline = YES + } else if (all == NO) { + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + iferr (call ap_update (gp, Memi[aps+current-1], line, apid, + apbeam, rval, low, high)) { + call erract (EA_WARN) + statline = YES + } + } else { + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + rval = rval - center + do i = 1, naps { + call ap_values (i, Memi[aps], line, apid, + apbeam, center, low, high) + center = center + rval + iferr (call ap_update (gp, Memi[aps+i-1], line, apid, + apbeam, center, low, high)) { + call erract (EA_WARN) + statline = YES + } + } + } + case LOWER: # :lower - Set lower aperture limit + if (current == 0) + goto done_ + call gargr (rval) + if (nscan() == 1) { + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + call printf ("low %g") + call pargr (low) + statline = YES + } else if (all == NO) { + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + iferr (call ap_update (gp, Memi[aps+current-1], line, apid, + apbeam, center, rval, high)) { + call erract (EA_WARN) + statline = YES + } + } else { + do i = 1, naps { + call ap_values (i, Memi[aps], line, apid, + apbeam, center, low, high) + iferr (call ap_update (gp, Memi[aps+i-1], line, apid, + apbeam, center, rval, high)) + call erract (EA_WARN) { + statline = YES + } + } + } + case UPPER: # :upper - Set upper aperture limit + if (current == 0) + goto done_ + call gargr (rval) + if (nscan() == 1) { + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + call printf ("high %g") + call pargr (high) + statline = YES + } else if (all == NO) { + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + iferr (call ap_update (gp, Memi[aps+current-1], line, apid, + apbeam, center, low, rval)) { + call erract (EA_WARN) + statline = YES + } + } else { + do i = 1, naps { + call ap_values (i, Memi[aps], line, apid, + apbeam, center, low, high) + iferr (call ap_update (gp, Memi[aps+i-1], line, apid, + apbeam, center, low, rval)) { + call erract (EA_WARN) + statline = YES + } + } + } + case APTITLE: + if (current == 0) + goto done_ + call gargwrd (Memc[wrd], SZ_LINE) + if (nscan() == 1) { + call printf ("title %s") + if (AP_TITLE(Memi[aps+current-1]) != NULL) + call pargstr (Memc[AP_TITLE(Memi[aps+current-1])]) + else + call pargstr ("[NONE]") + statline = YES + } else { + call reset_scan () + call gargwrd (Memc[str], SZ_LINE) + call gargstr (Memc[str], SZ_LINE) + if (AP_TITLE(Memi[aps+current-1]) == NULL) + call malloc (AP_TITLE(Memi[aps+current-1]), SZ_APTITLE, + TY_CHAR) + call strcpy (Memc[str+1], + Memc[AP_TITLE(Memi[aps+current-1])], SZ_APTITLE) + } + } + + } else { + Memc[wrd+j-1] = EOS + switch (Memc[wrd+j]) { + case 'b': + call gargb (bval) + if (nscan() < 2) { + call printf ("%s %b") + call pargstr (Memc[wrd]) + call pargb (apgetb (Memc[wrd])) + statline = YES + } else + call apputb (Memc[wrd], bval) + case 'i': + call gargi (ival) + if (nscan() < 2) { + call printf ("%s %d") + call pargstr (Memc[wrd]) + call pargi (apgeti (Memc[wrd])) + statline = YES + } else + call apputi (Memc[wrd], ival) + case 'r': + call gargr (rval) + if (nscan() < 2) { + call printf ("%s %g") + call pargstr (Memc[wrd]) + call pargr (apgetr (Memc[wrd])) + statline = YES + } else + call apputr (Memc[wrd], rval) + case 's': + call gargwrd (Memc[str], SZ_LINE) + if (nscan() < 2) { + call apgstr (Memc[wrd], Memc[str], SZ_LINE) + call printf ("%s %s") + call pargstr (Memc[wrd]) + call pargstr (Memc[str]) + statline = YES + } else + call appstr (Memc[wrd], Memc[str]) + } + } + +done_ call sfree (sp) + +end diff --git a/noao/twodspec/apextract/apcopy.x b/noao/twodspec/apextract/apcopy.x new file mode 100644 index 00000000..e697bf88 --- /dev/null +++ b/noao/twodspec/apextract/apcopy.x @@ -0,0 +1,28 @@ +include "apertures.h" + +# AP_COPY -- Make a copy of an aperture. +# The title is not copied. + +procedure ap_copy (apin, apout) + +pointer apin # Aperture to copy +pointer apout # New copy + +int i + +begin + # Allocate memory, transfer the aperture parameters, and call procedures + # which copy the offset curve and background parameters. + call ap_alloc (apout) + AP_ID(apout) = AP_ID(apin) + AP_BEAM(apout) = AP_BEAM(apin) + AP_AXIS(apout) = AP_AXIS(apin) + do i = 1, 2 { + AP_CEN(apout, i) = AP_CEN(apin, i) + AP_LOW(apout, i) = AP_LOW(apin, i) + AP_HIGH(apout, i) = AP_HIGH(apin, i) + } + call ap_cvset (apin, apout) + call ic_open (AP_IC(apout)) + call ic_copy (AP_IC(apin), AP_IC(apout)) +end diff --git a/noao/twodspec/apextract/apcveval.x b/noao/twodspec/apextract/apcveval.x new file mode 100644 index 00000000..09e5beb5 --- /dev/null +++ b/noao/twodspec/apextract/apcveval.x @@ -0,0 +1,19 @@ +include <math/curfit.h> + +# AP_CVEVAL -- Interface to CVEVAL that avoids extrapolation. +# This is necessary because if the tracing was truncated due to loss +# of the profile the trace limits will be smaller than the image axis. +# In the longer term the aperture limits along the dispersion should be +# used to limit the extent of the spectrum. + +real procedure ap_cveval (cv, x) + +pointer cv #I CURFIT pointer +real x #I Point to be evaluated. + +real x1, cvstatr(), cveval() + +begin + x1 = min (max (x, cvstatr(cv,CVXMIN)), cvstatr(cv,CVXMAX)) + return (cveval (cv, x1)) +end diff --git a/noao/twodspec/apextract/apcvset.x b/noao/twodspec/apextract/apcvset.x new file mode 100644 index 00000000..656187d5 --- /dev/null +++ b/noao/twodspec/apextract/apcvset.x @@ -0,0 +1,47 @@ +include <math/curfit.h> +include "apertures.h" + +# AP_CVSET -- Set the trace curve. +# If the input template aperture is NULL then the output trace curve +# is set to a constant zero otherwise a copy from the input template +# aperture is made. + +procedure ap_cvset (apin, apout) + +pointer apin # Input template aperture +pointer apout # Output aperture + +int apaxis, dispaxis, ncoeffs +real a, b, c[1] +pointer sp, coeffs + +int cvstati() + +begin + if (AP_CV(apout) != NULL) + call cvfree (AP_CV(apout)) + + if (apin == NULL) { + # Determine the aperture and alternate axes. + apaxis = AP_AXIS(apout) + dispaxis = mod (apaxis, 2) + 1 + + # Determine the limits over which the curve is defined. + a = AP_CEN(apout, dispaxis) + AP_LOW(apout, dispaxis) + b = AP_CEN(apout, dispaxis) + AP_HIGH(apout, dispaxis) + if (a == b) + b = b + 1 + + # Set the curve to a legendre polynomial of order 1 and value 0. + c[1] = 0. + call cvset (AP_CV(apout), LEGENDRE, a, b, c, 1) + } else { + # Use a SAVE and RESTORE to copy the CURFIT data. + call smark (sp) + ncoeffs = cvstati (AP_CV(apin), CVNSAVE) + call salloc (coeffs, ncoeffs, TY_REAL) + call cvsave (AP_CV(apin), Memr[coeffs]) + call cvrestore (AP_CV(apout), Memr[coeffs]) + call sfree (sp) + } +end diff --git a/noao/twodspec/apextract/apdb.x b/noao/twodspec/apextract/apdb.x new file mode 100644 index 00000000..8bfb5244 --- /dev/null +++ b/noao/twodspec/apextract/apdb.x @@ -0,0 +1,314 @@ +include <math/curfit.h> +include <pkg/dttext.h> +include "apertures.h" + +# AP_DBWRITE -- Write aperture data to the database. The database is obtained +# with a CL query. + +procedure ap_dbwrite (image, aps, naps) + +char image[ARB] # Image +pointer aps # Apertures +int naps + +int i, j, ncoeffs +pointer sp, database, str, dt, coeffs, ap + +int cvstati(), ic_geti() +real ic_getr() +bool strne() +pointer dtmap1() + +errchk dtmap1 + +begin + # Set the aperture database file name and map as a NEW_FILE. + # The file name is "ap" appended with the image name with the + # special image section characters replaced by '_'. + # The reason for making image sections separate database + # files rather than combining all database entries for an image + # in one file is that then previous entries can be deleted + # by using NEW_FILE mode which deletes any existing database + # file before writing out the new apertures. + + call smark (sp) + call salloc (database, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + + call clgstr ("database", Memc[database], SZ_FNAME) + if ((Memc[database] == EOS) || (image[1] == EOS)) { + call sfree (sp) + return + } + + # Map the database file name replacing special characters with '_'. + call sprintf (Memc[str], SZ_LINE, "ap%s") + call pargstr (image) + for (i=str; Memc[i] != EOS; i = i + 1) + switch (Memc[i]) { + case '[', ':', ',',']','*',' ', '/': + Memc[i] = '_' + } + dt = dtmap1 (Memc[database], Memc[str], NEW_FILE) + + # Write aperture entries for all apertures. + for (j = 0; j < naps; j = j + 1) { + ap = Memi[aps+j] + + call dtptime (dt) + call dtput (dt, "begin\taperture %s %d %g %g\n") + call pargstr (image) + call pargi (AP_ID(ap)) + call pargr (AP_CEN(ap, 1)) + call pargr (AP_CEN(ap, 2)) + if (AP_TITLE(ap) != NULL) { + call dtput (dt, "\ttitle\t%s\n") + call pargstr (Memc[AP_TITLE(ap)]) + } + call dtput (dt, "\timage\t%s\n") + call pargstr (image) + call dtput (dt, "\taperture\t%d\n") + call pargi (AP_ID(ap)) + call dtput (dt, "\tbeam\t%d\n") + call pargi (AP_BEAM(ap)) + call dtput (dt, "\tcenter\t%g %g\n") + call pargr (AP_CEN(ap, 1)) + call pargr (AP_CEN(ap, 2)) + call dtput (dt, "\tlow\t%g %g\n") + call pargr (AP_LOW(ap, 1)) + call pargr (AP_LOW(ap, 2)) + call dtput (dt, "\thigh\t%g %g\n") + call pargr (AP_HIGH(ap, 1)) + call pargr (AP_HIGH(ap, 2)) + if (AP_IC(ap) != NULL) { + call dtput (dt, "\tbackground\n") + call dtput (dt, "\t\txmin %g\n") + call pargr (ic_getr (AP_IC(ap), "xmin")) + call dtput (dt, "\t\txmax %g\n") + call pargr (ic_getr (AP_IC(ap), "xmax")) + call dtput (dt, "\t\tfunction %s\n") + call ic_gstr (AP_IC(ap), "function", Memc[str], SZ_LINE) + call pargstr (Memc[str]) + call dtput (dt, "\t\torder %d\n") + call pargi (ic_geti (AP_IC(ap), "order")) + call dtput (dt, "\t\tsample %s\n") + call ic_gstr (AP_IC(ap), "sample", Memc[str], SZ_LINE) + call pargstr (Memc[str]) + call dtput (dt, "\t\tnaverage %d\n") + call pargi (ic_geti (AP_IC(ap), "naverage")) + call dtput (dt, "\t\tniterate %d\n") + call pargi (ic_geti (AP_IC(ap), "niterate")) + call dtput (dt, "\t\tlow_reject %g\n") + call pargr (ic_getr (AP_IC(ap), "low")) + call dtput (dt, "\t\thigh_reject %g\n") + call pargr (ic_getr (AP_IC(ap), "high")) + call dtput (dt, "\t\tgrow %g\n") + call pargr (ic_getr (AP_IC(ap), "grow")) + } + + # Write out the curve. + call dtput (dt, "\taxis\t%d\n") + call pargi (AP_AXIS(ap)) + ncoeffs = cvstati (AP_CV(ap), CVNSAVE) + call malloc (coeffs, ncoeffs, TY_REAL) + call cvsave (AP_CV(ap), Memr[coeffs]) + call dtput (dt, "\tcurve\t%d\n") + call pargi (ncoeffs) + do i = 1, ncoeffs { + call dtput (dt, "\t\t%g\n") + call pargr (Memr[coeffs+i-1]) + } + call mfree (coeffs, TY_REAL) + + call dtput (dt, "\n") + } + call dtunmap (dt) + + # Log the write operation unless the output file is "last". + if (strne (image, "last")) { + call sprintf (Memc[str], SZ_LINE, + "DATABASE - %d apertures for %s written to %s") + call pargi (naps) + call pargstr (image) + call pargstr (Memc[database]) + call ap_log (Memc[str], YES, YES, NO) + call appstr ("ansdbwrite1", "no") + } + + call sfree (sp) +end + + +# AP_DBREAD - Get aperture information from the database. +# If no apertures are found then the input apertures are unchanged. +# The database is obtained with a CL query. + +procedure ap_dbread (image, aps, naps) + +char image[ARB] # Image +pointer aps # Apertures +int naps # Number of apertures + +int i, j, n, ncoeffs +pointer sp, database, str, ap, dt, coeffs + +bool strne() +int dtgeti() +real dtgetr() +pointer dtmap1() + +errchk dtmap1 + +begin + # Return if the database or image are undefined. + call smark (sp) + call salloc (database, SZ_FNAME, TY_CHAR) + call clgstr ("database", Memc[database], SZ_FNAME) + + if ((Memc[database] == EOS) || (image[1] == EOS)) { + call sfree (sp) + return + } + + # Set the aperture database file name and map it. + # The file name is "ap" appended with the image name with the + # special image section characters replaced by '_'. + call salloc (str, SZ_LINE, TY_CHAR) + call sprintf (Memc[str], SZ_LINE, "ap%s") + call pargstr (image) + for (i=str; Memc[i] != EOS; i = i + 1) + switch (Memc[i]) { + case '[', ':', ',',']','*',' ', '/': + Memc[i] = '_' + } + + # If an error occurs return the error. + dt = dtmap1 (Memc[database], Memc[str], READ_ONLY) + + # Read through the database finding records matching the input image. + n = naps + naps = 0 + do i = 1, DT_NRECS(dt) { + + call dtgstr (dt, i, "image", Memc[str], SZ_LINE) + if (strne (Memc[str], image)) + next + + # If an aperture is found delete any input apertures. + if (naps == 0) + for (j = 0; j < n; j = j + 1) + call ap_free (Memi[aps+j]) + + if (mod (naps, 100) == 0) + call realloc (aps, naps+100, TY_POINTER) + + call ap_alloc (ap) + ifnoerr (call dtgstr (dt, i, "title", Memc[str], SZ_LINE)) { + call malloc (AP_TITLE(ap), SZ_APTITLE, TY_CHAR) + call strcpy (Memc[str], Memc[AP_TITLE(ap)], SZ_APTITLE) + } + AP_ID(ap) = dtgeti (dt, i, "aperture") + iferr (AP_BEAM(ap) = dtgeti (dt, i, "beam")) + AP_BEAM(ap) = AP_ID(ap) + call dtgstr (dt, i, "center", Memc[str], SZ_LINE) + call sscan (Memc[str]) + call gargr (AP_CEN(ap, 1)) + call gargr (AP_CEN(ap, 2)) + call dtgstr (dt, i, "low", Memc[str], SZ_LINE) + call sscan (Memc[str]) + call gargr (AP_LOW(ap, 1)) + call gargr (AP_LOW(ap, 2)) + call dtgstr (dt, i, "high", Memc[str], SZ_LINE) + call sscan (Memc[str]) + call gargr (AP_HIGH(ap, 1)) + call gargr (AP_HIGH(ap, 2)) + ifnoerr (call dtgstr (dt, i, "background", Memc[str], SZ_LINE)) { + call ic_open (AP_IC(ap)) + call ic_putr (AP_IC(ap), "xmin", dtgetr (dt, i, "xmin")) + call ic_putr (AP_IC(ap), "xmax", dtgetr (dt, i, "xmax")) + call dtgstr (dt, i, "function", Memc[str], SZ_LINE) + call ic_pstr (AP_IC(ap), "function", Memc[str]) + call ic_puti (AP_IC(ap), "order", dtgeti (dt, i, "order")) + call dtgstr (dt, i, "sample", Memc[str], SZ_LINE) + call ic_pstr (AP_IC(ap), "sample", Memc[str]) + call ic_puti (AP_IC(ap), "naverage", dtgeti (dt, i, "naverage")) + call ic_puti (AP_IC(ap), "niterate", dtgeti (dt, i, "niterate")) + call ic_putr (AP_IC(ap), "low", dtgetr (dt, i, "low_reject")) + call ic_putr (AP_IC(ap), "high", dtgetr (dt, i, "high_reject")) + call ic_putr (AP_IC(ap), "grow", dtgetr (dt, i, "grow")) + } + + AP_AXIS(ap) = dtgeti (dt, i, "axis") + ncoeffs = dtgeti (dt, i, "curve") + call malloc (coeffs, ncoeffs, TY_REAL) + call dtgar (dt, i, "curve", Memr[coeffs], ncoeffs, ncoeffs) + call cvrestore (AP_CV(ap), Memr[coeffs]) + call mfree (coeffs, TY_REAL) + + Memi[aps+naps] = ap + naps = naps + 1 + } + call dtunmap (dt) + + # Log the read operation. + call sprintf (Memc[str], SZ_LINE, + "DATABASE - %d apertures read for %s from %s") + call pargi (naps) + call pargstr (image) + call pargstr (Memc[database]) + call ap_log (Memc[str], YES, YES, NO) + + # If no apertures were found then reset the number to the input value. + if (naps == 0) + naps = n + else + call appstr ("ansdbwrite1", "no") + + call sfree (sp) +end + + +# AP_DBACCESS - Check if a database file can be accessed. +# This does not check the contents of the file. +# The database is obtained with a CL query. + +int procedure ap_dbaccess (image) + +char image[ARB] # Image +int access # Database file access? + +int i +pointer sp, database, str, dt +pointer dtmap1() +errchk dtmap1 + +begin + call smark (sp) + call salloc (database, SZ_FNAME, TY_CHAR) + call clgstr ("database", Memc[database], SZ_FNAME) + + if ((Memc[database] != EOS) && (image[1] != EOS)) { + # Set the aperture database file name and map it. + # The file name is "ap" appended with the image name with the + # special image section characters replaced by '_'. + call salloc (str, SZ_LINE, TY_CHAR) + call sprintf (Memc[str], SZ_LINE, "ap%s") + call pargstr (image) + for (i=str; Memc[i] != EOS; i = i + 1) + switch (Memc[i]) { + case '[', ':', ',',']','*',' ', '/': + Memc[i] = '_' + } + + iferr { + dt = dtmap1 (Memc[database], Memc[str], READ_ONLY) + call dtunmap (dt) + access = YES + } then + access = NO + } else + access = NO + + call sfree (sp) + return (access) +end diff --git a/noao/twodspec/apextract/apdebug.par b/noao/twodspec/apextract/apdebug.par new file mode 100644 index 00000000..6b9fc8f9 --- /dev/null +++ b/noao/twodspec/apextract/apdebug.par @@ -0,0 +1,156 @@ +dispaxis = 2 +database = "database" +verbose = yes +logfile = "logfile" +plotfile = " " + +apall1.input = +apall1.nfind = +apall1.output = "" +apall1.apertures = "" +apall1.format = "multispec" +apall1.references = "" +apall1.profiles = "" +apall1.interactive = yes +apall1.find = yes +apall1.recenter = no +apall1.resize = no +apall1.edit = yes +apall1.trace = yes +apall1.fittrace = no +apall1.extract = yes +apall1.extras = yes +apall1.review = no +apall1.line = INDEF +apall1.nsum = 10 +apall1.lower = -5. +apall1.upper = 5. +apall1.apidtable = "" +apall1.b_function = "chebyshev" +apall1.b_order = 1 +apall1.b_sample = "-10:-6,6:10" +apall1.b_naverage = -3 +apall1.b_niterate = 0 +apall1.b_low_reject = 3. +apall1.b_high_reject = 3. +apall1.b_grow = 0. +apall1.width = 5. +apall1.radius = 10. +apall1.threshold = 0. +apall1.minsep = 5. +apall1.maxsep = 1000. +apall1.order = "increasing" +apall1.aprecenter = "" +apall1.npeaks = INDEF +apall1.shift = yes +apall1.llimit = INDEF +apall1.ulimit = INDEF +apall1.ylevel = 0.1 +apall1.peak = yes +apall1.bkg = yes +apall1.r_grow = 0. +apall1.avglimits = no +apall1.t_nsum = 10 +apall1.t_step = 10 +apall1.t_width = 5. +apall1.t_nlost = 3 +apall1.t_function = "legendre" +apall1.t_order = 2 +apall1.t_sample = "*" +apall1.t_naverage = 1 +apall1.t_niterate = 0 +apall1.t_low_reject = 3. +apall1.t_high_reject = 3. +apall1.t_grow = 0. +apall1.background = "none" +apall1.skybox = 1 +apall1.weights = "none" +apall1.pfit = "fit1d" +apall1.clean = no +apall1.saturation = INDEF +apall1.readnoise = "0." +apall1.gain = "1." +apall1.lsigma = 4. +apall1.usigma = 4. +apall1.nsubaps = 1 + +apall1.e_output = +apall1.e_profiles = +apall1.dbwrite = "yes" +apall1.initialize = yes +apall1.nclean = 0.5 +apall1.niterate = 5 +apall1.polysep = 0.90 +apall1.polyorder = 10 + +apall1.ansclobber = "no" +apall1.ansclobber1 = "no" +apall1.ansdbwrite = "yes" +apall1.ansdbwrite1 = "yes" +apall1.ansedit = "yes" +apall1.ansextract = "yes" +apall1.ansfind = "yes" +apall1.ansfit = "yes" +apall1.ansfitscatter = "yes" +apall1.ansfitsmooth = "yes" +apall1.ansfitspec = "yes" +apall1.ansfitspec1 = "yes" +apall1.ansfittrace = "yes" +apall1.ansfittrace1 = "yes" +apall1.ansflat = "yes" +apall1.ansnorm = "yes" +apall1.ansrecenter = "yes" +apall1.ansresize = "yes" +apall1.ansreview = "yes" +apall1.ansreview1 = "yes" +apall1.ansscat = "yes" +apall1.anssmooth = "yes" +apall1.anstrace = "yes" + +apall1.ansclobber.p_mode = "h" +apall1.ansclobber1.p_mode = "h" +apall1.ansdbwrite.p_mode = "h" +apall1.ansdbwrite1.p_mode = "h" +apall1.ansedit.p_mode = "h" +apall1.ansextract.p_mode = "h" +apall1.ansfind.p_mode = "h" +apall1.ansfit.p_mode = "h" +apall1.ansfitscatter.p_mode = "h" +apall1.ansfitsmooth.p_mode = "h" +apall1.ansfitspec.p_mode = "h" +apall1.ansfitspec1.p_mode = "h" +apall1.ansfittrace.p_mode = "h" +apall1.ansfittrace1.p_mode = "h" +apall1.ansflat.p_mode = "h" +apall1.ansnorm.p_mode = "h" +apall1.ansrecenter.p_mode = "h" +apall1.ansresize.p_mode = "h" +apall1.ansreview.p_mode = "h" +apall1.ansreview1.p_mode = "h" +apall1.ansscat.p_mode = "h" +apall1.anssmooth.p_mode = "h" +apall1.anstrace.p_mode = "h" + +apall1.ansclobber.p_prompt = "h" +apall1.ansclobber1.p_prompt = "h" +apall1.ansdbwrite.p_prompt = "h" +apall1.ansdbwrite1.p_prompt = "h" +apall1.ansedit.p_prompt = "h" +apall1.ansextract.p_prompt = "h" +apall1.ansfind.p_prompt = "h" +apall1.ansfit.p_prompt = "h" +apall1.ansfitscatter.p_prompt = "h" +apall1.ansfitsmooth.p_prompt = "h" +apall1.ansfitspec.p_prompt = "h" +apall1.ansfitspec1.p_prompt = "h" +apall1.ansfittrace.p_prompt = "h" +apall1.ansfittrace1.p_prompt = "h" +apall1.ansflat.p_prompt = "h" +apall1.ansnorm.p_prompt = "h" +apall1.ansrecenter.p_prompt = "h" +apall1.ansresize.p_prompt = "h" +apall1.ansreview.p_prompt = "h" +apall1.ansreview1.p_prompt = "h" +apall1.ansscat.p_prompt = "h" +apall1.anssmooth.p_prompt = "h" +apall1.anstrace.p_prompt = "h" diff --git a/noao/twodspec/apextract/apdefault.par b/noao/twodspec/apextract/apdefault.par new file mode 100644 index 00000000..7868197c --- /dev/null +++ b/noao/twodspec/apextract/apdefault.par @@ -0,0 +1,14 @@ +# APDEFAULT + +lower,r,h,-5.,,,Lower aperture limit relative to center +upper,r,h,5.,,,Upper aperture limit relative to center +apidtable,s,h,"",,,"Aperture ID table +" +b_function,s,h,"chebyshev","chebyshev|legendre|spline1|spline3",,Background function +b_order,i,h,1,1,,Background function order +b_sample,s,h,"-10:-6,6:10",,,Background sample regions +b_naverage,i,h,-3,,,Background average or median +b_niterate,i,h,0,0,,Background rejection iterations +b_low_reject,r,h,3.,0.,,Background lower rejection sigma +b_high_reject,r,h,3.,0.,,Background upper rejection sigma +b_grow,r,h,0.,0.,,Background rejection growing radius diff --git a/noao/twodspec/apextract/apdefault.x b/noao/twodspec/apextract/apdefault.x new file mode 100644 index 00000000..bea10f7c --- /dev/null +++ b/noao/twodspec/apextract/apdefault.x @@ -0,0 +1,42 @@ +include <imhdr.h> +include "apertures.h" + +# AP_DEFAULT -- Create a default aperture. +# The aperture ID, beam, axis, and the aperture center in both dimensions +# are specified. The aperture limits along the dispersion axis are set to +# the full size of the image while along the dispersion axis they are queried. +# The default offset curve is a constant zero curve. + +procedure ap_default (im, apid, apbeam, apaxis, apcenter, dispcenter, ap) + +pointer im # IMIO pointer +int apid # Aperture ID +int apbeam # Aperture beam number +int apaxis # Aperture axis +real apcenter # Center along the aperture axis +real dispcenter # Center along the dispersion axis +pointer ap # Aperture pointer + +int dispaxis +real apgetr() + +begin + dispaxis = mod (apaxis, 2) + 1 + + call ap_alloc (ap) + AP_ID(ap) = apid + AP_BEAM(ap) = apbeam + AP_AXIS(ap) = apaxis + AP_CEN(ap, apaxis) = apcenter + AP_LOW(ap, apaxis) = apgetr ("lower") + if (IS_INDEFR(AP_LOW(ap,apaxis))) + call error (1, "INDEF not allowed (lower)") + AP_HIGH(ap, apaxis) = apgetr ("upper") + if (IS_INDEFR(AP_HIGH(ap,apaxis))) + call error (1, "INDEF not allowed (upper)") + AP_CEN(ap, dispaxis) = dispcenter + AP_LOW(ap, dispaxis) = 1 - AP_CEN(ap, dispaxis) + AP_HIGH(ap, dispaxis) = IM_LEN(im, dispaxis) - AP_CEN(ap, dispaxis) + call ap_cvset (NULL, ap) + call ap_icset (NULL, ap, IM_LEN(im, apaxis)) +end diff --git a/noao/twodspec/apextract/apdelete.x b/noao/twodspec/apextract/apdelete.x new file mode 100644 index 00000000..1956a331 --- /dev/null +++ b/noao/twodspec/apextract/apdelete.x @@ -0,0 +1,23 @@ +# AP_DELETE -- Delete the specified aperture and return a new current aperture. + +procedure ap_delete (current, aps, naps) + +int current # Return current aperture index +pointer aps[ARB] # Aperture data +int naps # Number of apertures + +int i + +begin + if (current < 1) + return + + call ap_free (aps[current]) + for (i = current; i < naps; i = i + 1) + aps[i] = aps[i+1] + + aps[naps] = NULL + + naps = naps - 1 + current = min (naps, current) +end diff --git a/noao/twodspec/apextract/apdemos/apdemo1.cl b/noao/twodspec/apextract/apdemos/apdemo1.cl new file mode 100644 index 00000000..04704034 --- /dev/null +++ b/noao/twodspec/apextract/apdemos/apdemo1.cl @@ -0,0 +1,14 @@ +# Create demo data if needed. +artdata +mkexample ("multifiber", "apdemo", errors=no, verbose=yes, list=no) +bye +imdelete ("apdemo.ms.??h", verify=no) + +# Set parameters. +verbose = yes +logfile = "" +plotfile = "" +unlearn apall + +# Execute playback. +stty (playback="apdemos$apdemo1.dat", verify=no, delay=500) diff --git a/noao/twodspec/apextract/apdemos/apdemo1.dat b/noao/twodspec/apextract/apdemos/apdemo1.dat new file mode 100644 index 00000000..c718b423 --- /dev/null +++ b/noao/twodspec/apextract/apdemos/apdemo1.dat @@ -0,0 +1,14 @@ +\O=NOAO/IRAF V2.10DEVELOP valdes@puppis Tue 13:26:44 31-Jul-90 +\T=gterm +\G=gterm +apall\n +apdemo\n +\n +4\n +\n +no\n +\n +no\n +no\n +\n +no\n diff --git a/noao/twodspec/apextract/apdemos/apdemos.cl b/noao/twodspec/apextract/apdemos/apdemos.cl new file mode 100644 index 00000000..3b040ef7 --- /dev/null +++ b/noao/twodspec/apextract/apdemos/apdemos.cl @@ -0,0 +1,17 @@ +procedure apdemos (demo) + +int demo {prompt="Demo number"} + +begin + int demonum + file demofile + + if ($nargs == 0) + type ("apdemos$apdemos.men") + demonum = demo + demofile = "apdemos$apdemo" // demonum // ".cl" + if (access (demofile)) + cl (< demofile) + else + error (1, "Invalid demo number " // demonum) +end diff --git a/noao/twodspec/apextract/apdemos/apdemos.men b/noao/twodspec/apextract/apdemos/apdemos.men new file mode 100644 index 00000000..4e0ca6e1 --- /dev/null +++ b/noao/twodspec/apextract/apdemos/apdemos.men @@ -0,0 +1,3 @@ + MENU of APEXTRACT Demonstrations + + 1 - Simple demo of APALL diff --git a/noao/twodspec/apextract/apdemos/apdemosdb/aplast b/noao/twodspec/apextract/apdemos/apdemosdb/aplast new file mode 100644 index 00000000..93f85ea9 --- /dev/null +++ b/noao/twodspec/apextract/apdemos/apdemosdb/aplast @@ -0,0 +1,111 @@ +# Wed 11:02:05 22-Aug-90 +begin aperture last 1 60.57419 256. + image last + aperture 1 + beam 1 + center 60.57419 256. + low -3.111816 -255. + high 2.949428 256. + background + xmin -100. + xmax 100. + function chebyshev + order 1 + sample -10:-6,6:10 + naverage -3 + niterate 0 + low_reject 3. + high_reject 3. + grow 0. + axis 1 + curve 6 + 2. + 2. + 1. + 512. + 0.02659256 + 0.5026957 + +# Wed 11:02:05 22-Aug-90 +begin aperture last 2 70.70531 256. + image last + aperture 2 + beam 2 + center 70.70531 256. + low -2.926423 -255. + high 2.899426 256. + background + xmin -100. + xmax 100. + function chebyshev + order 1 + sample -10:-6,6:10 + naverage -3 + niterate 0 + low_reject 3. + high_reject 3. + grow 0. + axis 1 + curve 6 + 2. + 2. + 1. + 512. + -0.002646168 + 0.5073752 + +# Wed 11:02:05 22-Aug-90 +begin aperture last 3 80.78613 256. + image last + aperture 3 + beam 3 + center 80.78613 256. + low -2.953142 -255. + high 2.970872 256. + background + xmin -100. + xmax 100. + function chebyshev + order 1 + sample -10:-6,6:10 + naverage -3 + niterate 0 + low_reject 3. + high_reject 3. + grow 0. + axis 1 + curve 6 + 2. + 2. + 1. + 512. + 0.01349655 + 0.5075101 + +# Wed 11:02:05 22-Aug-90 +begin aperture last 4 90.8806 256. + image last + aperture 4 + beam 4 + center 90.8806 256. + low -2.823333 -255. + high 2.915152 256. + background + xmin -100. + xmax 100. + function chebyshev + order 1 + sample -10:-6,6:10 + naverage -3 + niterate 0 + low_reject 3. + high_reject 3. + grow 0. + axis 1 + curve 6 + 2. + 2. + 1. + 512. + 0.022075 + 0.5081324 diff --git a/noao/twodspec/apextract/apedit.key b/noao/twodspec/apextract/apedit.key new file mode 100644 index 00000000..d28a8856 --- /dev/null +++ b/noao/twodspec/apextract/apedit.key @@ -0,0 +1,74 @@ + APEXTRACT CURSOR KEY SUMMARY + +? Print help j Set beam number u Set upper limit(s) +a Toggle all flag l Set lower limit(s) w Window graph +b Set background(s) m Mark aperture y Y level limit(s) +c Center aperture(s) n New uncentered ap. z Resize aperture(s) +d Delete aperture(s) o Order ap. numbers I Interrupt +e Extract spectra q Quit + Next aperture +f Find apertures r Redraw graph - Previous aperture +g Recenter aperture(s) s Shift aperture(s) . Nearest aperture +i Set aperture ID t Trace aperture(s) + + APEXTRACT COLON COMMAND SUMMARY + +:apertures :center :npeaks :show :t_width +:apidtable :clean :nsubaps :skybox :threshold +:avglimits :database :nsum :t_function :title +:b_function :extras :order :t_grow :ulimit +:b_grow :gain :parameters :t_high_reject :upper +:b_high_reject :image :peak :t_low_reject :usigma +:b_low_reject :line :plotfile :t_naverage :weights +:b_naverage :llimit :r_grow :t_niterate :width +:b_niterate :logfile :radius :t_nlost :write +:b_order :lower :read :t_nsum :ylevel +:b_sample :lsigma :readnoise :t_order +:background :maxsep :saturation :t_sample +:bkg :minsep :shift :t_step + + APEXTRACT CURSOR KEYS + +? Print help +a Toggle the ALL flag +b an Set background fitting parameters +c an Center aperture(s) +d an Delete aperture(s) +e an Extract spectra (see APSUM) +f Find apertures up to the requested number (see APFIND) +g an Recenter aperture(s) (see APRECENTER) +i n Set aperture ID +j n Set aperture beam number +l ac Set lower limit of current aperture at cursor position +m Define and center a new aperture on the profile near the cursor +n Define a new aperture centered at the cursor +o n Enter desired aperture number for cursor selected aperture and remaining + apertures are reordered using apidtable and maxsep parameters + (see APFIND for ordering algorithm) +q Quit +r Redraw the graph +s an Shift the center(s) of the current aperture to the cursor position +t ac Trace aperture positions (see APTRACE) +u ac Set upper limit of current aperture at cursor position +w Window the graph using the window cursor keys +y an Set aperture limits to intercept the data at the cursor y position +z an Resize aperture(s) (see APRESIZE) +. n Select the aperture nearest the cursor to be the current aperture ++ c Select the next aperture (in ID) to be the current aperture +- c Select the previous aperture (in ID) to be the current aperture +I Interrupt task immediately. Database information is not saved. + +The letter a following the key indicates if all apertures are affected when +the ALL flag is set. The letter c indicates that the key affects the +current aperture while the letter n indicates that the key affects the +aperture whose center is nearest the cursor. + + APEXTRACT COLON COMMANDS + +:show [file] Print a list of the apertures (default file is STDOUT) +:parameters [file] Print current parameter values (default file is STDOUT) +:read [name] Read apertures from database (default to the current image) +:write [name] Write apertures to database (default to the current image) + +The remaining colon commands are task parameters and print the current +value if no value is given or reset the current value to that specified. +Use :parameters to see current parameter values. diff --git a/noao/twodspec/apextract/apedit.par b/noao/twodspec/apextract/apedit.par new file mode 100644 index 00000000..8e6c15f5 --- /dev/null +++ b/noao/twodspec/apextract/apedit.par @@ -0,0 +1,17 @@ +# APEDIT + +input,s,a,,,,List of input images to edit +apertures,s,h,"",,,Apertures +references,s,h,"",,,"Reference images +" +interactive,b,h,yes,,,Run task interactively? +find,b,h,no,,,Find apertures? +recenter,b,h,no,,,Recenter apertures? +resize,b,h,no,,,Resize apertures? +edit,b,h,yes,,,"Edit apertures? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,10,,,Number of dispersion lines to sum or median +width,r,h,5.,0.,,Profile centering width +radius,r,h,10.,,,Profile centering radius +threshold,r,h,0.,0.,,Detection threshold for profile centering diff --git a/noao/twodspec/apextract/apedit.x b/noao/twodspec/apextract/apedit.x new file mode 100644 index 00000000..e7170e92 --- /dev/null +++ b/noao/twodspec/apextract/apedit.x @@ -0,0 +1,604 @@ +include <error.h> +include <gset.h> +include <imhdr.h> +include <mach.h> +include <pkg/gtools.h> +include "apertures.h" + +define HELP "noao$twodspec/apextract/apedit.key" +define PROMPT "apextract options" + +# Sort flags +define ORDER "|increasing|decreasing|" + +# AP_EDIT -- Define and edit apertures. This is the main interactive +# procedure for manipulating apertures. The selected dispersion line +# is graphed with possible summing of neighboring lines and then +# cursor keys are used to define new apertures or edit existing apertures. +# Note that the value of line may be changed. + +procedure ap_edit (image, line, nsum, aps, naps) + +char image[SZ_FNAME] # Image to be edited +int line # Dispersion line +int nsum # Number of dispersion lines to sum + +pointer aps # Aperture pointers +int naps # Number of apertures + +char cmd[SZ_LINE] +int i, npts, apaxis, dispaxis, statline +int current, newgraph, newim, newdata, all, wcs, key, apid, apbeam +real center, low, high, wx, wy +bool peak +pointer im, imdata, title +pointer sp, x, wts, apdef, gp, gt, ic_gt, cv, str, output, profiles, ids + +int gt_gcur(), apgwrd(), scan(), nscan() +real ap_cveval(), ap_center() +bool ap_answer() +pointer gt_init() +errchk ap_getdata, ap_gopen, ap_default + +define new_ 10 +define beep_ 99 + +begin + # Query user. + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call sprintf (Memc[str], SZ_LINE, "Edit apertures for %s?") + call pargstr (image) + if (!ap_answer ("ansedit", Memc[str])) { + call sfree (sp) + return + } + + # Set flags. + all = NO + + # Get user aperture ID's + call ap_gids (ids) + + # Map the image and get the image data. +new_ call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, title) + newdata = NO + newim = NO + + # Allocate additional memory. + call salloc (x, npts, TY_REAL) + call salloc (wts, npts, TY_REAL) + call salloc (output, SZ_FNAME, TY_CHAR) + call salloc (profiles, SZ_FNAME, TY_CHAR) + + # Set the default aperture and delete apertures which do not have + # the correct aperture axis. + call ap_default (im, INDEFI, 1, apaxis, INDEFR, real (line), apdef) + dispaxis = mod (apaxis, 2) + 1 + for (i = naps; i > 0; i = i - 1) + if (AP_AXIS(Memi[aps+i-1]) != apaxis) + call ap_delete (i, Memi[aps], naps) + + # Set up the graphics. + call ap_gopen (gp) + gt = gt_init() + call gt_sets (gt, GTTITLE, "Define and Edit Apertures") + call gt_sets (gt, GTPARAMS, Memc[title]) + + # Enter cursor loop. + current = min (1, naps) + key = 'r' + wy = INDEF + repeat { + statline = NO + + # For those keys affecting the nearest aperture set the current + # aperture to be the aperture nearest the cursor. + switch (key) { + case '.','b','c','d','e','g','i','j','o','t','y','z': + # The current aperture is the one nearest the cursor. + call ap_nearest (current, line, Memi[aps], naps, wx) + } + + # Set the current aperture values. + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + + # Select the operation to be performed. + switch (key) { + case '?': # Print help text. + call gpagefile (gp, HELP, PROMPT) + + case ':': # Colon commands. + if (cmd[1] == '/') + call gt_colon (cmd, gp, gt, newgraph) + else { + call ap_colon (cmd, im, gp, apdef, aps, naps, current, + image, line, nsum, all, newgraph, newim, newdata, + statline) + if (newim == YES) + break + if (newdata == YES) { + call mfree (imdata, TY_REAL) + call mfree (title, TY_CHAR) + call imunmap (im) + call ap_getdata (image, line, nsum, im, imdata, npts, + apaxis, title) + call gt_sets (gt, GTPARAMS, Memc[title]) + newdata = NO + newgraph = YES + } + call ap_free (apdef) + iferr (call ap_default (im, INDEFI, 1, apaxis, INDEFR, + real (line), apdef)) + call erract (EA_WARN) + } + + case '.': # Select current aperture. This has been done already. + ; + + case '+': # Go to next aperture. + current = min (naps, current + 1) + + case '-': # Go to last aperture. + current = min (naps, max (1, current - 1)) + + case 'a': # Toggle all flag + if (all == NO) + all = YES + else + all = NO + + case 'b': # Set background fitting parameters. + if (current == 0) + goto beep_ + + do i = 1, npts { + Memr[x+i-1] = i - center + Memr[wts+i-1] = 1 + } + + if (ic_gt == NULL) { + ic_gt = gt_init() + call gt_sets (ic_gt, GTTYPE, "line") + wx = max (10., high - low) + call gt_setr (ic_gt, GTXMIN, low - 2 * wx) + call gt_setr (ic_gt, GTXMAX, high + 2 * wx) + } + + call sprintf (Memc[str], SZ_LINE, + "Set Background Subtraction for Aperture %d") + call pargi (apid) + call gt_sets (ic_gt, GTTITLE, Memc[str]) + + if (AP_IC(Memi[aps+current-1]) == NULL) + call ap_icset (apdef, Memi[aps+current-1], npts) + + call icg_fit (AP_IC(Memi[aps+current-1]), gp, "gcur", + ic_gt, cv, Memr[x], Memr[imdata], Memr[wts], npts) + call cvfree (cv) + + # Set background limits + call ap_icset (Memi[aps+current-1], Memi[aps+current-1], npts) + + if ((naps > 1) && (all == YES)) + do i = 1, naps + if (i != current) + call ap_icset (Memi[aps+current-1], + Memi[aps+i-1], npts) + newgraph = YES + + case 'c': # Center current aperture or all apertures. + if (current == 0) + goto beep_ + + if ((naps == 1) || (all == NO)) { + center = ap_center (center, Memr[imdata], npts) + if (!IS_INDEF(center)) + call ap_update (gp, Memi[aps+current-1], line, apid, + apbeam, center, low, high) + } else { + do i = 1, naps { + call ap_values (i, Memi[aps], line, apid, + apbeam, center, low, high) + center = ap_center (center, Memr[imdata], npts) + if (!IS_INDEF(center)) + call ap_update (gp, Memi[aps+i-1], line, apid, + apbeam, center, low, high) + } + } + + case 'd': # Delete apertures + if (current == 0) + goto beep_ + + call gseti (gp, G_PLTYPE, 0) + if ((naps == 1) || (all == NO)) { + call ap_gmark (gp, line, Memi[aps+current-1], 1) + call ap_delete (current, Memi[aps], naps) + call ap_gscur (current, gp, line, Memi[aps], wy) + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + } else { + do i = 1, naps { + call ap_gmark (gp, line, Memi[aps+i-1], 1) + call ap_free (Memi[aps+i-1]) + } + naps = 0 + current = 0 + } + call gseti (gp, G_PLTYPE, 1) + + case 'e': # Sum extraction + if (current == 0) + goto beep_ + + call imunmap (im) + call apgstr ("e_output", Memc[output], SZ_FNAME) + call apgstr ("e_profiles", Memc[profiles], SZ_FNAME) + call apgstr ("format", Memc[str], SZ_LINE) + call appstr ("ansreview", "yes") + call appstr ("ansreview1", "yes") + call appstr ("ansclobber", "yes") + call appstr ("ansclobber1", "yes") + if (all == NO) + call ap_extract (image, Memc[output], + Memc[str], Memc[profiles], Memi[aps+current-1], 1) + else + call ap_extract (image, Memc[output], + Memc[str], Memc[profiles], Memi[aps], naps) + call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, + title) + newgraph = YES + + case 'f': # Find apertures + if (current == 0) + call ap_findnew (line, Memr[imdata], npts, + apdef, aps, naps) + else + call ap_findnew (line, Memr[imdata], npts, + Memi[aps+current-1], aps, naps) + call ap_gmark (gp, line, Memi[aps], naps) + current = naps + + case 'g': # Apply recenter algorithm. + if (current == 0) + goto beep_ + + call imunmap (im) + if (all == NO) { + call gseti (gp, G_PLTYPE, 0) + call ap_gmark (gp, line, Memi[aps+current-1], 1) + call ap_recenter (image, line, nsum, + Memi[aps+current-1], 1, YES) + call gseti (gp, G_PLTYPE, 1) + call ap_gmark (gp, line, Memi[aps+current-1], 1) + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + } else { + call gseti (gp, G_PLTYPE, 0) + do i = 1, naps + call ap_gmark (gp, line, Memi[aps+i-1], 1) + call ap_recenter (image, line, nsum, Memi[aps], naps, YES) + call gseti (gp, G_PLTYPE, 1) + do i = 1, naps + call ap_gmark (gp, line, Memi[aps+i-1], 1) + } + call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, + title) + + case 'i': # Set aperture ID + if (current == 0) + goto beep_ + + repeat { + call printf ("Aperture (%d) = ") + call pargi (AP_ID(Memi[aps+current-1])) + call flush (STDOUT) + if (scan () != EOF) { + call gargi (apid) + if (nscan() == 1) { + if (apid < 1) { + call printf ( + "Aperture numbers < 1 are not allowed: ") + } else { + for (i=1; i<=naps; i=i+1) + if (i != current && + apid == AP_ID(Memi[aps+i-1])) + break + if (i <= naps) { + call printf ("Aperture %d already used: ") + call pargi (apid) + } else { + AP_ID(Memi[aps+current-1]) = apid + call ap_ids (Memi[aps+current-1], 1, ids) + break + } + } + } else + break + } + } + + case 'j': # Set beam number + if (current == 0) + goto beep_ + + repeat { + call printf ("Beam (%d) = ") + call pargi (AP_BEAM(Memi[aps+current-1])) + call flush (STDOUT) + if (scan () != EOF) { + call gargi (apbeam) + if (nscan() == 1) { +# if (apbeam < 0) { +# call printf ( +# "Beam numbers < 0 are not allowed: ") +# } else { + if (all == NO) + AP_BEAM(Memi[aps+current-1]) = apbeam + else + do i = 1, naps + AP_BEAM(Memi[aps+i-1]) = apbeam + break +# } + } else + break + } + } + + case 'l': # Set the low limit. + if (current == 0) + goto beep_ + + wx = wx - center + if ((naps == 1) || (all == NO)) + call ap_update (gp, Memi[aps+current-1], line, apid, + apbeam, center, wx, high) + else { + do i = 1, naps { + call ap_values (i, Memi[aps], line, apid, + apbeam, center, low, high) + call ap_update (gp, Memi[aps+i-1], line, apid, + apbeam, center, wx, high) + } + } + + case 'm', 'n': # Define a new aperture. + if (mod (naps, 100) == 0) + call realloc (aps, naps+100, TY_POINTER) + + if (key == 'm') + wx = ap_center (wx, Memr[imdata], npts) + + if (!IS_INDEF(wx)) { + naps = naps + 1 + if (naps > 1) + call ap_copy (Memi[aps+current-1], Memi[aps+naps-1]) + else + call ap_copy (apdef, Memi[aps+naps-1]) + + AP_ID(Memi[aps+naps-1]) = INDEFI + AP_CEN(Memi[aps+naps-1], apaxis) = wx - + ap_cveval (AP_CV(Memi[aps+naps-1]), real (line)) + AP_CEN(Memi[aps+naps-1], dispaxis) = line + AP_LOW(Memi[aps+naps-1], dispaxis) = + 1 - AP_CEN(Memi[aps+naps-1], dispaxis) + AP_HIGH(Memi[aps+naps-1], dispaxis) = IM_LEN(im, dispaxis) - + AP_CEN(Memi[aps+naps-1], dispaxis) + + call ap_icset (Memi[aps+naps-1], Memi[aps+naps-1], npts) + + current = naps + i = apgwrd ("order", cmd, SZ_LINE, ORDER) + call ap_sort (current, Memi[aps], naps, i) + call ap_ids (Memi[aps], naps, ids) + call ap_titles (Memi[aps+current-1], 1, ids) + + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + call ap_gmark (gp, line, Memi[aps+current-1], 1) + } + + case 'o': # Order the aperture and beam numbers + if (naps == 0) + goto beep_ + + do i = 1, naps + if (i != current) + AP_ID(Memi[aps+i-1]) = INDEFI + + call printf ("Aperture (%d) = ") + call pargi (AP_ID(Memi[aps+current-1])) + call flush (STDOUT) + if (scan () != EOF) { + call gargi (apid) + if (nscan() == 1) { + AP_ID(Memi[aps+current-1]) = apid + AP_BEAM(Memi[aps+current-1]) = apid + } + } + + i = apgwrd ("order", cmd, SZ_LINE, ORDER) + call ap_sort (current, Memi[aps], naps, i) + call ap_ids (Memi[aps], naps, ids) + + # Reset the titles + do i = 1, naps + if (AP_TITLE(Memi[aps+i-1]) != NULL) + call mfree (AP_TITLE(Memi[aps+i-1]), TY_CHAR) + call ap_titles (Memi[aps], naps, ids) + + newgraph = YES + + case 'r': # Redraw the graph. + newgraph = YES + + case 's': # Shift apertures + if (current == 0) + goto beep_ + + call printf ("Center aperture %d (no)? ") + call pargi (AP_ID(Memi[aps+current-1])) + call flush (STDOUT) + if (scan () != EOF) { + call gargb (peak) + if (nscan() == 1 && peak) { + wy = ap_center (wx, Memr[imdata], npts) + if (!IS_INDEF(wy)) + wx = wy + } + } + + if ((naps == 1) || (all == NO)) + call ap_update (gp, Memi[aps+current-1], line, apid, + apbeam, wx, low, high) + else { + wx = wx - center + do i = 1, naps { + call ap_values (i, Memi[aps], line, apid, + apbeam, center, low, high) + call ap_update (gp, Memi[aps+i-1], line, apid, + apbeam, center + wx, low, high) + } + } + + case 't': # Trace. + if (current == 0) + goto beep_ + + call imunmap (im) + call appstr ("ansfittrace1", "yes") + if (all == NO) + call ap_trace (image, line, Memi[aps+current-1], 1, YES) + else + call ap_trace (image, line, Memi[aps], naps, YES) + call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, + title) + newgraph = YES + + case 'u': # Set the upper limit. + if (current == 0) + goto beep_ + + wx = wx - center + if ((naps == 1) || (all == NO)) + call ap_update (gp, Memi[aps+current-1], line, apid, + apbeam, center, low, wx) + else { + do i = 1, naps { + call ap_values (i, Memi[aps], line, apid, + apbeam, center, low, high) + call ap_update (gp, Memi[aps+i-1], line, apid, + apbeam, center, low, wx) + } + } + + case 'w': # Window the graph. + call gt_window (gt, gp, "gcur", newgraph) + + case 'y': # Set aperture limits at the y level. + if (current == 0) + goto beep_ + + if ((naps == 1) || (all == NO)) { + low = -npts + high = npts + call ap_ylevel (Memr[imdata], npts, wy, false, false, 0., + center, low, high) + call ap_update (gp, Memi[aps+current-1], line, apid, + apbeam, center, low, high) + } else { + do i = 1, naps { + call ap_values (i, Memi[aps], line, apid, + apbeam, center, low, high) + low = -npts + high = npts + call ap_ylevel (Memr[imdata], npts, wy, false, false, + 0., center, low, high) + call ap_update (gp, Memi[aps+i-1], line, apid, + apbeam, center, low, high) + } + } + + case 'z': # Apply resize algorithm. + if (current == 0) + goto beep_ + + call imunmap (im) + if (all == NO) { + call gseti (gp, G_PLTYPE, 0) + call ap_gmark (gp, line, Memi[aps+current-1], 1) + call ap_resize (image, line, nsum, + Memi[aps+current-1], 1, YES) + call gseti (gp, G_PLTYPE, 1) + call ap_gmark (gp, line, Memi[aps+current-1], 1) + call ap_values (current, Memi[aps], line, apid, + apbeam, center, low, high) + } else { + call gseti (gp, G_PLTYPE, 0) + do i = 1, naps + call ap_gmark (gp, line, Memi[aps+i-1], 1) + call ap_resize (image, line, nsum, Memi[aps], naps, YES) + call gseti (gp, G_PLTYPE, 1) + do i = 1, naps + call ap_gmark (gp, line, Memi[aps+i-1], 1) + } + call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, + title) + + case 'I': # Interrupt + call fatal (0, "Interrupt") + + default: # Ring bell for unrecognized commands. +beep_ call printf ("Invalid or unrecognized command\007") + statline = YES + } + + # Update the graph if needed. + if (newgraph == YES) { + call ap_graph (gp, gt, Memr[imdata], npts, line, + Memi[aps], naps) + newgraph = NO + } + + # Set the cursor to the current aperture and print the current + # aperture on the status line. + call ap_gscur (current, gp, line, Memi[aps], wy) + if (statline == NO) + call ap_print (current, line, all, Memi[aps]) + + } until (gt_gcur ("gcur", wx, wy, wcs, key, cmd, SZ_LINE) == EOF) + + # Log the editing operation. + call sprintf (Memc[str], SZ_LINE, "EDIT - %d apertures edited for %s") + call pargi (naps) + call pargstr (image) + call ap_log (Memc[str], YES, NO, NO) + + # Free memory. + call ap_fids (ids) + call mfree (imdata, TY_REAL) + call mfree (title, TY_CHAR) + call imunmap (im) + call gt_free (gt) + call gt_free (ic_gt) + call ap_free (apdef) + + # If a new image is desired loop back. + if (newim == YES) { + call clgstr ("database", Memc[output], SZ_LINE) + call sprintf (Memc[str], SZ_LINE, + "Write apertures for %s to %s") + call pargstr (image) + call pargstr (Memc[output]) + if (ap_answer ("ansdbwrite", Memc[str])) + call ap_dbwrite (image, aps, naps) + call strcpy (cmd, image, SZ_FNAME) + call ap_dbread (image, aps, naps) + goto new_ + } + + call appstr ("ansdbwrite1", "yes") + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apertures.h b/noao/twodspec/apextract/apertures.h new file mode 100644 index 00000000..aeb4bd94 --- /dev/null +++ b/noao/twodspec/apextract/apertures.h @@ -0,0 +1,32 @@ +# Aperture Definition + +# Aperture structure -- The aperture structure consists of an integer +# identification number, a title, the center of the aperture, the lower +# and upper limits of the aperture measured relative to the center, the +# axis for a curve giving an offset relative to the center, the CURFIT +# pointer describing the curve and an ICFIT pointer for background +# subtraction. The center and lower and upper limits are pairs of real +# numbers in the order column value and line value. The edges of the +# aperture are given by: +# +# low column = center column + low column offset + curve (line) +# high column = center column + high column offset + curve (line) +# low line = center line + low line offset + curve (column) +# high line = center line + high line offset + curve (column) +# +# The curve is aplied to the column positions if the curve axis is 1 and +# to the line positions if the curve axis is 2. + +define AP_LEN 13 # Length of aperture structure +define SZ_APTITLE 60 # Length of aperture title + +define AP_ID Memi[$1] # Aperture ID +define AP_TITLE Memi[$1+1] # Pointer to title +define AP_BEAM Memi[$1+2] # Aperture beam number +define AP_CEN Memr[P2R($1+3+$2-1)] # Aperture center +define AP_LOW Memr[P2R($1+5+$2-1)] # Aperture limit +define AP_HIGH Memr[P2R($1+7+$2-1)] # Aperture limit +define AP_AXIS Memi[$1+9] # Axis for curve +define AP_CV Memi[$1+10] # Aperture curve +define AP_IC Memi[$1+11] # ICFIT pointer +define AP_SELECT Memi[$1+12] # Aperture selected? diff --git a/noao/twodspec/apextract/apextract.cl b/noao/twodspec/apextract/apextract.cl new file mode 100644 index 00000000..035ce189 --- /dev/null +++ b/noao/twodspec/apextract/apextract.cl @@ -0,0 +1,33 @@ +#{ APEXTRACT -- Aperture extraction package + +package apextract + +task apall, + apedit, + apfind, + apfit, + apflatten, + apmask, + apnormalize, + aprecenter, + apresize, + apscatter, + apnoise, + apsum, + aptrace = "apextract$x_apextract.e" +task apparams = "apextract$apparams.par" +task apall1 = "apextract$apall1.par" +task apfit1 = "apextract$apfit1.par" +task apflat1 = "apextract$apflat1.par" +task apnorm1 = "apextract$apnorm1.par" +task apnoise1 = "apextract$apnoise1.par" +task apdefault = "apextract$apdefault.par" +task apscat1 = "apextract$apscat1.par" +task apscat2 = "apextract$apscat2.par" + +set apdemos = "apextract$apdemos/" +task apdemos.pkg = "apdemos$apdemos.cl" + +hidetask apparams, apall1, apfit1, apflat1, apnorm1, apscat1, apscat2, apnoise1 + +clbye diff --git a/noao/twodspec/apextract/apextract.hd b/noao/twodspec/apextract/apextract.hd new file mode 100644 index 00000000..ad17623d --- /dev/null +++ b/noao/twodspec/apextract/apextract.hd @@ -0,0 +1,27 @@ +# Help directory for the APEXTRACT package. + +$doc = "./doc/" + +apall hlp=doc$apall.hlp +apdefault hlp=doc$apdefault.hlp +apdemos hlp=doc$apdemos.hlp +apedit hlp=doc$apedit.hlp +apfind hlp=doc$apfind.hlp +apfit hlp=doc$apfit.hlp +apflatten hlp=doc$apflatten.hlp +apmask hlp=doc$apmask.hlp +apnoise hlp=doc$apnoise.hlp +apnormalize hlp=doc$apnormalize.hlp +aprecenter hlp=doc$aprecenter.hlp +apresize hlp=doc$apresize.hlp +apscatter hlp=doc$apscatter.hlp +apsum hlp=doc$apsum.hlp +aptrace hlp=doc$aptrace.hlp + +package hlp=doc$apextract.hlp, sys=doc$apextractsys.hlp +apbackground hlp=doc$apbackground.hlp +approfiles hlp=doc$approfiles.hlp +apvariance hlp=doc$apvariance.hlp +extras hlp=doc$apextras.hlp + +revisions sys=Revisions diff --git a/noao/twodspec/apextract/apextract.men b/noao/twodspec/apextract/apextract.men new file mode 100644 index 00000000..c0db0005 --- /dev/null +++ b/noao/twodspec/apextract/apextract.men @@ -0,0 +1,23 @@ + apall - Extract 1D spectra (all parameters in one task) + apdefault - Set the default aperture parameters and apidtable + apdemos - Various tutorial demonstrations + apedit - Edit apertures interactively + apfind - Automatically find spectra and define apertures + apfit - Fit 2D spectra and output the fit, difference, or ratio + apflatten - Remove overall spectral and profile shapes from flat fields + apnoise - Compute and examine noise characteristics of spectra + apmask - Create and IRAF pixel list mask of the apertures + apnormalize - Normalize 2D apertures by 1D functions + aprecenter - Recenter apertures + apresize - Resize apertures + apscatter - Fit and subtract scattered light + apsum - Extract 1D spectra + aptrace - Trace positions of spectra + + ADDITIONAL HELP TOPICS + + apbackground - Background subtraction algorithms + approfiles - Profile determination algorithms + apvariance - Extractions, variance weighting, cleaning, and noise model + extras - Information about the extra information in 3D images + package - Package parameters and general description of package diff --git a/noao/twodspec/apextract/apextract.par b/noao/twodspec/apextract/apextract.par new file mode 100644 index 00000000..8b153ec8 --- /dev/null +++ b/noao/twodspec/apextract/apextract.par @@ -0,0 +1,8 @@ +# APEXTRACT Package + +dispaxis,i,h,2,1,2,"Dispersion axis (1=along lines, 2=along columns)" +database,f,h,"database",,,Database +verbose,b,h,no,,,Verbose output? +logfile,s,h,"",,,Text log file +plotfile,s,h,"",,,Plot file +version,s,h,"APEXTRACT V3.0: August 1990" diff --git a/noao/twodspec/apextract/apextract.x b/noao/twodspec/apextract/apextract.x new file mode 100644 index 00000000..176ab251 --- /dev/null +++ b/noao/twodspec/apextract/apextract.x @@ -0,0 +1,1834 @@ +include <error.h> +include <imhdr.h> +include <mach.h> +include <math/iminterp.h> +include <pkg/gtools.h> +include "apertures.h" + +# Background fitting types +define BACKGROUND "|none|average|median|minimum|fit|" +define B_NONE 1 +define B_AVERAGE 2 +define B_MEDIAN 3 +define B_MINIMUM 4 +define B_FIT 5 + +# Weight types +define WEIGHTS "|none|variance|" +define W_NONE 1 +define W_VARIANCE 2 + +# Profile fitting algorithms +define P_FIT "|fit1d|fit2d|" +define P_FIT1D 1 +define P_FIT2D 2 + +# Output formats +define FORMATS "|onedspec|multispec|echelle|strip|normalize|flatten\ + |ratio|difference|fit|noise|" +define ONEDSPEC 1 # Individual 1D spectra +define MULTISPEC 2 # Multiple spectra +define ECHELLE 3 # Echelle spectra +define STRIP 4 # Strip spectra +define NORM 5 # Normalized spectra +define FLAT 6 # Flat spectra +define RATIO 7 # Ratio of data to model +define DIFF 8 # Difference of data and model +define FIT 9 # Model +define NOISE 10 # Noise calculation + + +# AP_EXTRACT -- Extract spectra by a weighted sum across the apertures. +# +# This routine does clobber checks on the output images, manages the I/O +# from the input image in as big of pieces as possible, and loops through +# each aperture calling routines to determine the sky, do any fitting and +# extraction, and output the spectra. +# The extraction may be either a simple, unweighted extraction +# which is very fast or a weighted extraction using CCD noise +# parameters. The weights require dividing out the basic spectrum and +# smoothing the 2D spectral profile. The general approach of variance +# weighting is described by K. Horne (PASP V98, P609, 1986). The +# smoothing has two algorithms, fitting columns or lines parallel to the +# dispersion axis for nearly aligned spectra or fitting a 2D function +# using a method given by T. Marsh (PASP V101, P1032, 1989). The profile +# may also be used to reject cosmic rays by iteration. +# +# The extractions require enough memory to get at least one aperture plus +# background (if needed) into memory. If possible the region containing +# all the apertures is read into memory. The target maximum amount of +# memory is set by the maxmimum size returned by BEGMEM and the +# appropriate working set size is requested. The optimal size can be +# tuned through BEGMEM, which references a machine dependent include +# file, if needed. The algorithm should work well (minimize I/O as well +# as paging) in all cases but very large image formats with highly tilted +# spectra (where aperture extraction along the image axes is not really +# appropriate). These memory requirements were chosen to minimize image +# I/O and because the variance weighted algorithms need to make multiple +# passes through the image. In principle simple, unweighted extractions +# with no sky smoothing can be done sequentially but this was not done in +# order to use nearly the same code for both weighted and unweighted +# cases. +# +# If using variance weighting and a profile image is given then it is used +# to determine the profile which is then applied to the target image +# during the final extraction. If the same profile image is used multiple +# times it would be more efficient to store the profile but then issues +# of consistency arise. For now this possible feature is not implemented. + +procedure ap_extract (input, output, format, profiles, aps, naps) + +char input[SZ_FNAME] # Input image +char output[SZ_FNAME] # Output image (optional root name) +char format[SZ_LINE] # Output format +char profiles[SZ_FNAME] # Profile filename (optional) +pointer aps[ARB] # Apertures +int naps # Number of apertures + +# CL parameters +int fmt # Output format +int bkg # Background type +int weights # Extraction weights +int pfit # Profile fitting algorithm +bool clean # Reject cosmic rays? +real gain # Photon/DN gain +real rdnoise # Read out noise +int nsubaps # Number of subapertures +int interptype # Edge interpolation type + +int i, j, k, napsex, aaxis, baxis, namax, na, nb, na1, interpbuf +int amin, amax, bmin, bmax +int new_size, old_size, max_size, best_size +real cmin, cmax, xmin, xmax, shift +pointer sp, str, bkgstr, wtstr, cleanstr, apsex +pointer a, b, c, astart, spec, specsky, specsig, raw, profile +pointer a1, a2, b1, b2, c1, c2, im, pim, ap, cv, ic, dbuf, pbuf, sbuf, svar, ptr +pointer asi + +bool clgetb(), apgetb(), strne() +int apgeti(), apgwrd(), begmem(), ap_check() +real apgimr(), ap_cveval(), ic_getr() +pointer ap_immap(), imgs2r(), imgl2r() +errchk salloc, malloc, ap_immap, imgs2r, imgl2r, asiinit +errchk ap_check, ap_skyeval, ap_profile, ap_variance, ap_output, apgimr + +begin + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + + napsex = 0 + do i = 1, naps + if (AP_SELECT(aps[i]) == YES) + napsex = napsex + 1 + if (napsex == 0) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - No apertures defined for %s") + call pargstr (input) + call ap_log (Memc[str], YES, NO, YES) + call sfree (sp) + return + } + + call salloc (bkgstr, SZ_FNAME, TY_CHAR) + call salloc (wtstr, SZ_FNAME, TY_CHAR) + call salloc (cleanstr, SZ_FNAME, TY_CHAR) + call salloc (apsex, napsex, TY_POINTER) + + # Select apertures to extract and fix possible limit error. + napsex = 0 + do i = 1, naps { + if (AP_LOW(aps[i],1) > AP_HIGH(aps[i],1)) { + xmax = AP_LOW(aps[i],1) + AP_LOW(aps[i],1) = AP_HIGH(aps[i],1) + AP_HIGH(aps[i],1) = xmax + } + if (AP_LOW(aps[i],2) > AP_HIGH(aps[i],2)) { + xmax = AP_LOW(aps[i],2) + AP_LOW(aps[i],2) = AP_HIGH(aps[i],2) + AP_HIGH(aps[i],2) = xmax + } + if (AP_SELECT(aps[i]) == NO) + next + Memi[apsex+napsex] = aps[i] + napsex = napsex + 1 + } + + # Get CL parameters + bkg = apgwrd ("background", Memc[bkgstr], SZ_FNAME, BACKGROUND) + pfit = apgwrd ("pfit", Memc[str], SZ_LINE, P_FIT) + clean = apgetb ("clean") + if (clean) + call strcpy ("yes", Memc[cleanstr], SZ_FNAME) + else + call strcpy ("no", Memc[cleanstr], SZ_FNAME) + nsubaps = apgeti ("nsubaps") + interptype = II_LINEAR + + # Do clobber checking. Return if output exists and not clobbering. + call apgstr ("ansclobber", Memc[str], SZ_LINE) + call appstr ("ansclobber1", Memc[str]) + fmt = ap_check (input, output, format, Memi[apsex], napsex, nsubaps) + if (fmt == 0) { + call sfree (sp) + return + } + + # Force weights depending on format or cleaning. + switch (fmt) { + case FLAT, RATIO, DIFF, FIT, NOISE: + weights = W_VARIANCE + default: + if (clean) { + call strcpy ("variance", Memc[wtstr], SZ_FNAME) + weights = W_VARIANCE + } else + weights = apgwrd ("weights", Memc[wtstr], SZ_FNAME, WEIGHTS) + } + + if (clgetb ("verbose")) { + call printf ("Extracting apertures ...\n") + call flush (STDOUT) + } + + # Open input image and profile image if given. Set axis parameters + # where 'a' is the aperture axis across the dispersion and 'b' is + # along the dispersion. + + im = ap_immap (input, aaxis, baxis) + namax = IM_LEN(im, aaxis) + nb = IM_LEN(im, baxis) + + pim = NULL + if (strne(profiles,input) && weights==W_VARIANCE && profiles[1]!=EOS) { + pim = ap_immap (profiles, i, j) + if (i!=aaxis||j!=baxis||IM_LEN(pim,i)!=namax||IM_LEN(pim,j)!=nb) { + call imunmap (pim) + call imunmap (im) + call sfree (sp) + call error (1, + "Input image and profile image are not compatible") + } + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Using profile image %s for %s") + call pargstr (profiles) + call pargstr (input) + call ap_log (Memc[str], YES, YES, NO) + } + + # Determine limits of apertures for use in defining memory requirements + # and I/O. + + call salloc (a, 2 * napsex, TY_INT) + call salloc (b, 2 * napsex, TY_INT) + call salloc (c, 2 * napsex, TY_REAL) + a1 = a - 1 + a2 = a1 + napsex + b1 = b - 1 + b2 = b1 + napsex + c1 = c - 1 + c2 = c1 + napsex + + # Initialize image interpolator for edge pixel weighting. + switch (interptype) { + case II_LINEAR: + interpbuf = 2 + case II_POLY3: + interpbuf = 3 + case II_SINC: + interpbuf = 16 + default: + interpbuf = 0 + } + if (interptype > 0) + call asiinit (asi, interptype) + else + asi = NULL + + na1 = 0 + do i = 1, napsex { + ap = Memi[apsex+i-1] + cv = AP_CV(ap) + ic = AP_IC(ap) + + # Dispersion axis limits + bmin = min (nb, max (1, nint (AP_CEN(ap,baxis)+AP_LOW(ap,baxis)))) + bmax = max (1, min (nb, nint (AP_CEN(ap,baxis)+AP_HIGH(ap,baxis)))) + + # Aperture axis shifts + if (cv != NULL) { + cmin = MAX_REAL + cmax = -MAX_REAL + do j = bmin, bmax { + shift = ap_cveval (cv, real (j)) + cmin = min (cmin, shift) + cmax = max (cmax, shift) + } + } else { + cmin = 0. + cmax = 0. + } + + # Background region limits. + xmin = AP_LOW(ap,aaxis) + xmax = AP_HIGH(ap,aaxis) + if (weights == W_VARIANCE) { + xmin = xmin - 2 + xmax = xmax + 2 + } + xmin = xmin - interpbuf + xmax = xmax + interpbuf + if (bkg != B_NONE && AP_IC(ap) != NULL) { + xmin = min (xmin, ic_getr (ic, "xmin")) + xmax = max (xmax, ic_getr (ic, "xmax")) + } + + Memi[a1+i] = min (namax, max (1, nint (AP_CEN(ap,aaxis)+xmin+cmin))) + Memi[a2+i] = max (1, min (namax, nint (AP_CEN(ap,aaxis)+xmax+cmax))) + Memi[b1+i] = bmin + Memi[b2+i] = bmax + Memr[c1+i] = cmin + Memr[c2+i] = cmax + } + call alimi (Memi[a], 2*napsex, amin, amax) + call alimi (Memi[b], 2*napsex, bmin, bmax) + + # The maximum size of the image in memory is 80% of the maximum + # working set size returned by begmem or 40% if a profile image + # is used. Later I/O may exceed this since at least one + # aperture + background is needed in memory. + + new_size = begmem (0, old_size, max_size) + namax = (amax - amin + 1) + nb = (bmax - bmin + 1) + if (pim == NULL) + namax = min (namax, int (0.8 * max_size / SZ_REAL / nb)) + else + namax = min (namax, int (0.8 * max_size / SZ_REAL / nb / 2)) + best_size = 1.2 * namax * nb * SZ_REAL + new_size = begmem (best_size, old_size, max_size) + + # Allocate auxilary memory. Some memory is only dependent on the + # number of dispersion points and subapertures and is the same for + # all apertures. Other memory, such as the sky and profile depend on + # the aperture widths and tilts which may vary. The input data is + # expected to have the aperture axis along the first dimension. If + # the image is in this orientation then the IMIO buffer is used. + # Otherwise sequential I/O is used and transposed into the allocated + # memory. + + iferr { + call salloc (astart, nb, TY_INT) + call salloc (spec, nsubaps * nb, TY_REAL) + if (weights == W_VARIANCE) { + call salloc (raw, nsubaps * nb, TY_REAL) + call salloc (specsig, nsubaps * nb, TY_REAL) + } else { + raw = NULL + specsig = NULL + } + profile = NULL + if (aaxis == 2) { + call calloc (dbuf, namax * nb, TY_REAL) + if (pim != NULL) + call calloc (pbuf, namax * nb, TY_REAL) + } + + # For variance weighting the computations are done in photon units. + if (weights == W_VARIANCE) { + gain = apgimr ("gain", im) + rdnoise = apgimr ("readnoise", im) + } else { + gain = 1 + rdnoise = 0 + } + + # Loop through each aperture doing the extractions. + amax = 0 + do i = 1, napsex { + ap = Memi[apsex+i-1] + + # Check if a new input data buffer is needed. As many apertures + # as possible are read at once within the given memory limits + # though at least one aperture must be read. Do a transpose if + # needed. + + if (Memi[a1+i] < amin || Memi[a2+i] > amax) { + amin = Memi[a1+i] + amax = Memi[a2+i] + do j = i, napsex { + amin = min (amin, Memi[a1+j]) + amax = max (amax, Memi[a2+j]) + na = amax - amin + 1 + if (na > namax) + break + } + + if (aaxis == 1) { + if (fmt == DIFF) { + call mfree (dbuf, TY_REAL) + call malloc (dbuf, na*nb, TY_REAL) + call amovr (Memr[imgs2r(im,amin,amax,bmin,bmax)], + Memr[dbuf], na*nb) + } else + dbuf = imgs2r (im, amin, amax, bmin, bmax) + } else { + if (na > namax) { + call mfree (dbuf, TY_REAL) + namax = na + call calloc (dbuf, namax * nb, TY_REAL) + } + do j = amin, amax { + sbuf = imgl2r (im, j) + sbuf = sbuf + bmin - 1 + ptr = dbuf + j - amin + do k = bmin, bmax { + Memr[ptr] = Memr[sbuf] + sbuf = sbuf + 1 + ptr = ptr + na + } + } + } + if (pim != NULL) { + if (aaxis == 1) + pbuf = imgs2r (pim, amin, amax, bmin, bmax) + else { + if (na > namax) { + call mfree (pbuf, TY_REAL) + namax = na + call calloc (pbuf, namax * nb, TY_REAL) + } + do j = amin, amax { + sbuf = imgl2r (pim, j) + sbuf = sbuf + bmin - 1 + ptr = pbuf + j - amin + do k = bmin, bmax { + Memr[ptr] = Memr[sbuf] + sbuf = sbuf + 1 + ptr = ptr + na + } + } + } + } + if (weights == W_VARIANCE && gain != 1.) { + j = na * nb + call amulkr (Memr[dbuf], gain, Memr[dbuf], j) + if (pim != NULL) + call amulkr (Memr[pbuf], gain, Memr[pbuf], j) + } + } + + # To minimize memory a variable integer offset is used to + # accomodate the aperture tilts. The offsets are stored in + # the astart array and the width of any one line determined. + # If a stored profile is used it is read and it is ASSUMED to + # be valid for the input aperture with the same ID. If no + # stored profile is found the profile fitting algorithm + # parameter determines whether to fit 1D function along the + # image axes (in which case all the profile offsets are the + # same) or if the Marsh algorithm for tilted spectra is + # used. In the latter the offsets can be adjusted to mimize + # memory and a buffer of two pixels around the aperture is + # required by the algorithm. + + if (weights == W_NONE) { + xmin = AP_CEN(ap,aaxis) + AP_LOW(ap,aaxis) + xmax = AP_CEN(ap,aaxis) + AP_HIGH(ap,aaxis) + xmin = xmin - interpbuf + xmax = xmax + interpbuf + na1 = nint (xmax) - nint (xmin) + 1 + cv = AP_CV(ap) + do j = bmin, bmax { + shift = ap_cveval (cv, real (j)) + Memi[astart+j-bmin] = nint (xmin + shift) + } + } else { + if (pfit == P_FIT1D) { + xmin = AP_CEN(ap,aaxis) + AP_LOW(ap,aaxis) + Memr[c1+i] + xmax = AP_CEN(ap,aaxis) + AP_HIGH(ap,aaxis) + Memr[c2+i] + xmin = xmin - interpbuf + xmax = xmax + interpbuf + na1 = nint (xmax) - nint (xmin) + 1 + call amovki (nint (xmin), Memi[astart], nb) + } else if (pfit == P_FIT2D) { + xmin = AP_CEN(ap,aaxis) + AP_LOW(ap,aaxis) - 2 + xmax = AP_CEN(ap,aaxis) + AP_HIGH(ap,aaxis) + 2 + xmin = xmin - interpbuf + xmax = xmax + interpbuf + na1 = nint (xmax) - nint (xmin) + 1 + cv = AP_CV(ap) + do j = bmin, bmax { + shift = ap_cveval (cv, real (j)) + Memi[astart+j-bmin] = nint (xmin + shift) + } + } + } + + # Do the sky or background determination if needed. An array + # of the same size as the 2D aperture is returned as well as + # a single estimate of the variance in the sky value at each + # line based on the fit. If a profile image is used then the + # sky is for the profile image and the object sky is + # determined later in order to reuse the sky buffers. + + if (bkg != B_NONE && AP_IC(ap) != NULL) { + call malloc (sbuf, na1 * nb, TY_REAL) + call malloc (svar, nb, TY_REAL) + call malloc (specsky, nsubaps * nb, TY_REAL) + if (pim == NULL) + call ap_skyeval (im, ap, dbuf, na, nb, amin, 1, + Memr[sbuf], Memr[svar], Memr[specsky], na1, nb, + Memi[astart], 1, nsubaps, rdnoise) + else + call ap_skyeval (pim, ap, pbuf, na, nb, amin, 1, + Memr[sbuf], Memr[svar], Memr[specsky], na1, nb, + Memi[astart], 1, nsubaps, rdnoise) + } else { + sbuf = NULL + svar = NULL + specsky = NULL + } + + # Use a quick sum for unweighted extraction. For weighed + # extractions we use either a previously determined profile + # or call the profile routine. If desired the profile is + # stored for later use. Then the variance weighted + # extraction routine is called. + + if (weights == W_NONE) + call ap_sum (ap, dbuf, na, nb, amin, 1, sbuf, na1, nb, + Memi[astart], 1, Memr[spec], nsubaps, asi) + else { + call malloc (profile, na1 * nb, TY_REAL) + if (pim == NULL) + call ap_profile (im, ap, dbuf, na, nb, amin, 1, sbuf, + svar, Memr[profile], na1, nb, Memi[astart], 1, + asi) + else { + call ap_profile (pim, ap, pbuf, na, nb, amin, 1, sbuf, + svar, Memr[profile], na1, nb, Memi[astart], 1, + asi) + if (sbuf != NULL) + call ap_skyeval (im, ap, dbuf, na, nb, amin, 1, + Memr[sbuf], Memr[svar], Memr[specsky], na1, nb, + Memi[astart], 1, nsubaps, rdnoise) + } + + call ap_variance (im, ap, dbuf, na, nb, amin, 1, sbuf, svar, + Memr[profile], na1, nb, Memi[astart], 1, Memr[spec], + Memr[raw], Memr[specsig], nsubaps, asi) + } + + # Output the extracted spectrum. The extras of sky, sigma, + # and unweighted spectrum may also be stored. If the extra + # information is not available the pointers will be NULL. + + if (weights == W_VARIANCE && gain != 1.) { + call adivkr (Memr[spec], gain, Memr[spec], nb) + if (raw != NULL) + call adivkr (Memr[raw], gain, Memr[raw], nb) + if (specsky != NULL) + call adivkr (Memr[specsky], gain, Memr[specsky], nb) + if (specsig != NULL) + call adivkr (Memr[specsig], gain, Memr[specsig], nb) + call amulkr (Memr[profile], gain, Memr[profile], nb*na1) + } + + call ap_output (input, output, format, Memc[bkgstr], + Memc[wtstr], Memc[cleanstr], gain, im, Memi[apsex], napsex, + i, nsubaps, spec, raw, specsky, specsig, dbuf, na, nb, amin, + 1, sbuf, profile, na1, nb, Memi[astart], 1) + + call mfree (profile, TY_REAL) + call mfree (sbuf, TY_REAL) + call mfree (svar, TY_REAL) + call mfree (specsky, TY_REAL) + } + + # Finish up and restore the working set size. + if (asi != NULL) + call asifree (asi) + if (pim != NULL) { + if (aaxis == 2) + call mfree (pbuf, TY_REAL) + call imunmap (pim) + } + if (aaxis == 2) + call mfree (dbuf, TY_REAL) + call imunmap (im) + call fixmem (old_size) + call sfree (sp) + + } then { + call mfree (profile, TY_REAL) + call mfree (sbuf, TY_REAL) + call mfree (svar, TY_REAL) + call mfree (specsky, TY_REAL) + + if (asi != NULL) + call asifree (asi) + if (pim != NULL) { + if (aaxis == 2) + call mfree (pbuf, TY_REAL) + call imunmap (pim) + } + if (aaxis == 2) + call mfree (dbuf, TY_REAL) + call imunmap (im) + call fixmem (old_size) + call sfree (sp) + + call erract (EA_ERROR) + } +end + + +# AP_CHECK -- Check if output spectra exist. If the user allows clobbering, +# delete the spectra. Return the format. + +int procedure ap_check (input, output, format, aps, naps, nsubaps) + +char input[ARB] # Input image name +char output[ARB] # Output root name +char format[ARB] # Output format +pointer aps[naps] # Apertures +int naps # Number of apertures +int nsubaps # Number of subapertures + +int i, j, fmt +pointer sp, name, name1, input1, ksection, ans + +int strdic(), imaccess(), stridxs() +bool streq(), ap_answer() + +begin + call smark (sp) + call salloc (name, SZ_LINE, TY_CHAR) + call salloc (name1, SZ_LINE, TY_CHAR) + call salloc (input1, SZ_LINE, TY_CHAR) + call salloc (ksection, SZ_LINE, TY_CHAR) + call salloc (ans, SZ_LINE, TY_CHAR) + + fmt = strdic (format, format, SZ_LINE, FORMATS) + call imgimage (input, Memc[input1], SZ_LINE) + + switch (fmt) { + case MULTISPEC, NORM, FLAT, RATIO, DIFF, FIT: + i = stridxs ("[", Memc[input1]) + if (i > 0) { + call strcpy (Memc[input1+i-1], Memc[ksection], SZ_LINE) + Memc[input1+i-1] = EOS + } else + Memc[ksection] = EOS + if (output[1] == EOS) + call strcpy (Memc[input1], Memc[name], SZ_LINE) + else + call strcpy (output, Memc[name], SZ_LINE) + + switch (fmt) { + case MULTISPEC: + if (streq (Memc[input1], Memc[name])) { + call strcat (".ms", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case NORM: + if (streq (Memc[input1], Memc[name])) { + call strcat (".norm", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case FLAT: + if (streq (Memc[input1], Memc[name])) { + call strcat (".flat", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case RATIO: + if (streq (Memc[input1], Memc[name])) { + call strcat (".ratio", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case DIFF: + if (streq (Memc[input1], Memc[name])) { + call strcat (".diff", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case FIT: + if (streq (Memc[input1], Memc[name])) { + call strcat (".fit", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + } + if (imaccess (Memc[name], 0) == YES) { + call sprintf (Memc[ans], SZ_LINE, + "Clobber existing output image %s?") + call pargstr (Memc[name]) + if (ap_answer ("ansclobber1", Memc[ans])) + call imdelete (Memc[name]) + else { + call sprintf (Memc[ans], SZ_LINE, + "EXTRACT - Output spectrum %s already exists") + call pargstr (Memc[name]) + call ap_log (Memc[ans], YES, NO, YES) + fmt = 0 + } + } + case ECHELLE: + if (output[1] == EOS) + call strcpy (Memc[input1], Memc[name], SZ_LINE) + else + call strcpy (output, Memc[name], SZ_LINE) + + do i = 1, nsubaps { + if (nsubaps == 1) + call strcpy (Memc[name], Memc[name1], SZ_LINE) + else { + call sprintf (Memc[name1], SZ_LINE, "%s%0*d") + call pargstr (Memc[name]) + call pargi (int(log10(real(nsubaps)))+1) + call pargi (i) + } + if (streq (Memc[input1], Memc[name])) { + call strcat (".ec", Memc[name1], SZ_LINE) + call strcat (Memc[ksection], Memc[name1], SZ_LINE) + } + + if (imaccess (Memc[name1], 0) == YES) { + call sprintf (Memc[ans], SZ_LINE, + "Clobber existing output image %s?") + call pargstr (Memc[name1]) + if (ap_answer ("ansclobber1", Memc[ans])) + call imdelete (Memc[name1]) + else { + call sprintf (Memc[ans], SZ_LINE, + "EXTRACT - Output spectrum %s already exists") + call pargstr (Memc[name1]) + call ap_log (Memc[ans], YES, NO, YES) + fmt = 0 + } + } + } + case ONEDSPEC, STRIP: + do i = 1, naps { + do j = 1, nsubaps { + call sprintf (Memc[name], SZ_LINE, "%s.%0*d") + if (output[1] == EOS) + call pargstr (Memc[input1]) + else + call pargstr (output) + call pargi (int(log10(real(nsubaps)))+4) + call pargi (AP_ID(aps[i])+(j-1)*1000) + if (imaccess (Memc[name], 0) == YES) { + call sprintf (Memc[ans], SZ_LINE, + "Clobber existing output image %s?") + call pargstr (Memc[name]) + if (ap_answer ("ansclobber1", Memc[ans])) + call imdelete (Memc[name]) + else { + call sprintf (Memc[ans], SZ_LINE, + "EXTRACT - Output spectrum %s already exists") + call pargstr (Memc[name]) + call ap_log (Memc[ans], YES, NO, YES) + fmt = 0 + } + } + } + } + case NOISE: + ; + default: + call sfree (sp) + call error (1, "EXTRACT - Unknown output format") + } + + call sfree (sp) + return (fmt) +end + + +# AP_OUTPUT -- Review the extracted spectra and write them to an image. +# This routine determines the output format and whether to also output sky +# unweighted, and sigma spectra. The appropriate header keywords have +# to be added. + +procedure ap_output (image, output, format, bkg, wt, clean, gain, in, aps, + naps, iap, nsubaps, spec, raw sky, sig, dbuf, nc, nl, c1, l1, sbuf, + profile, nx, ny, xs, ys) + +char image[ARB] # Input image name +char output[ARB] # Output root name +char format[ARB] # Output format +char bkg[ARB] # Background type +char wt[ARB] # Weight type +char clean[ARB] # Clean? +real gain # Gain +pointer in # Input IMIO pointer +pointer aps[naps] # Apertures +int naps # Number of apertures +int iap # Aperture +int nsubaps # Number of subapertures +pointer spec # Output spectrum +pointer raw # Output raw spectrum +pointer sky # Output sky +pointer sig # Output sigma +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +pointer sbuf # Sky values (NULL if none) +pointer profile # Profile (NULL if none) +int nx, ny # Size of sky and profile array +int xs[ny], ys # Origin of sky and profile array + +int fmt # Output format +bool extras # Include raw spectrum, sky, and sigma + +real low, high, step +int i, k, l, m, apid, apaxis, dispaxis +pointer sp, str, str1, name, name1, input, ksection +pointer ap, out, outsave, gt, apmw, buf +pointer sum2, sum4, nsum + +real clgetr() +int scan(), strdic(), imaccf(), stridxs() +bool streq(), ap_answer(), apgetb() +pointer immap(), imgl2r(), impl2r(), impl3r() +pointer gt_init(), apmw_open() +errchk immap, impl2r, impl3r, imps2r, ap_strip, ap_pstrip, apmw_open +errchk ap_fitspec, ap_lnorm, ap_cnorm, ap_lflat, ap_cflat + +begin + # Allocate string and file name arrays. + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (str1, SZ_LINE, TY_CHAR) + call salloc (name, SZ_LINE, TY_CHAR) + call salloc (name1, SZ_LINE, TY_CHAR) + call salloc (input, SZ_LINE, TY_CHAR) + call salloc (ksection, SZ_LINE, TY_CHAR) + + fmt = strdic (format, format, SZ_LINE, FORMATS) + extras = apgetb ("extras") + + ap = aps[iap] + apaxis = AP_AXIS(ap) + dispaxis = mod (apaxis, 2) + 1 + + # Set output name. + call imgimage (image, Memc[input], SZ_LINE) + i = stridxs ("[", Memc[input]) + if (i > 0) { + call strcpy (Memc[input+i-1], Memc[ksection], SZ_LINE) + Memc[input+i-1] = EOS + i = stridxs ("]", Memc[ksection]) + call strcpy (",append]", Memc[ksection+i-1], SZ_LINE) + } else + Memc[ksection] = EOS + if (output[1] == EOS) + call strcpy (Memc[input], Memc[name], SZ_LINE) + else + call strcpy (output, Memc[name], SZ_LINE) + + switch (fmt) { + case ECHELLE: + ; + case MULTISPEC: + if (streq (Memc[input], Memc[name])) { + call strcat (".ms", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case NORM: + if (streq (Memc[input], Memc[name])) { + call strcat (".norm", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case FLAT: + if (streq (Memc[input], Memc[name])) { + call strcat (".flat", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case RATIO: + if (streq (Memc[input], Memc[name])) { + call strcat (".ratio", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case DIFF: + if (streq (Memc[input], Memc[name])) { + call strcat (".diff", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case FIT: + if (streq (Memc[input], Memc[name])) { + call strcat (".fit", Memc[name], SZ_LINE) + call strcat (Memc[ksection], Memc[name], SZ_LINE) + } + case NOISE: + Memc[name] = EOS + } + + + # Set the review graph title. + call sprintf (Memc[str], SZ_LINE, "%s: %s - Aperture %s") + call pargstr (image) + call pargstr (IM_TITLE(in)) + call pargi (AP_ID(ap)) + + gt = gt_init () + call gt_sets (gt, GTTITLE, Memc[str]) + + # Query the user whether to review the extraction. + call sprintf (Memc[str], SZ_LINE, + "Review extracted spectrum for aperture %d from %s?") + call pargi (AP_ID(ap)) + call pargstr (image) + + # If reviewing graph the spectrum, do a cursor loop, and allow + # the user to skip the output or define a new output image. + if (ap_answer ("ansreview1", Memc[str])) { + call ap_graph1 (gt, Memr[spec], ny, nsubaps) + + if (fmt == ONEDSPEC && nsubaps == 1) { + call printf ( + "Output image name [use # to skip output] (%s): ") + call pargstr (Memc[name]) + call flush (STDOUT) + if (scan() != EOF) { + call gargwrd (Memc[str], SZ_LINE) + if (Memc[str] == '#') { + call gt_free (gt) + call sfree (sp) + return + } + if (Memc[str] != EOS) + call strcpy (Memc[str], Memc[name], SZ_LINE) + } + } + } + + # Output the image. + switch (fmt) { + case MULTISPEC: + if (iap == 1) { + out = immap (Memc[name], NEW_COPY, in) + + IM_PIXTYPE(out) = TY_REAL + IM_NDIM(out) = 1 + IM_LEN(out, 1) = ny + IM_LEN(out, 2) = nsubaps * naps + IM_LEN(out, 3) = 1 + if (extras) { + if (sky != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + if (raw != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + if (sig != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + } + if (IM_LEN(out, 2) > 1) + IM_NDIM(out) = 2 + if (IM_LEN(out, 3) > 1) + IM_NDIM(out) = 3 + + apmw = apmw_open (in, out, dispaxis, nsubaps*naps, ny) + + # Write BAND IDs. + k = 1 + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "spectrum - background %s, weights %s, clean %s") + call pargstr (bkg) + call pargstr (wt) + call pargstr (clean) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + if (extras) { + if (raw != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "raw - background %s, weights none, clean no") + call pargstr (bkg) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + } + if (sky != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "background - background %s") + call pargstr (bkg) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + } + if (sig != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "sigma - background %s, weights %s, clean %s") + call pargstr (bkg) + call pargstr (wt) + call pargstr (clean) + call imastr (out, Memc[str1], Memc[str]) + } + } + + do k = 1, naps { + low = AP_CEN(aps[k],apaxis) + AP_LOW(aps[k],apaxis) + high = AP_CEN(aps[k],apaxis) + AP_HIGH(aps[k],apaxis) + step = (high - low) / nsubaps + low = low - step + do l = 1, nsubaps { + apid = AP_ID(aps[k]) + (l - 1) * 1000 + low = low + step + high = low + step + call apmw_setap (apmw, (k-1)*nsubaps+l, + apid, AP_BEAM(aps[k]), low, high) + } + } + do k = 1, naps { + if (AP_TITLE(aps[k]) != NULL) { + do l = 1, nsubaps { + call sprintf (Memc[str], SZ_LINE, "APID%d") + call pargi ((k-1)*nsubaps+l) + call imastr (out, Memc[str], + Memc[AP_TITLE(aps[k])]) + } + } + } + } + + do l = 1, nsubaps { + k = (iap - 1) * nsubaps + l + buf = impl2r (out, k) + call amovr (Memr[spec+(l-1)*ny], Memr[buf], ny) + if (extras) { + m = 2 + if (raw != NULL) { + buf = impl3r (out, k, m) + call amovr (Memr[raw+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + if (sky != NULL) { + buf = impl3r (out, k, m) + call amovr (Memr[sky+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + if (sig != NULL) { + buf = impl3r (out, k, m) + call amovr (Memr[sig+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + } + } + if (iap == naps) { + call apmw_saveim (apmw, out, fmt) + call apmw_close (apmw) + call imunmap (out) + } + + if (Memc[name] != EOS) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d from %s --> %s") + call pargi (AP_ID(ap)) + call pargstr (image) + call pargstr (Memc[name]) + call ap_log (Memc[str], YES, YES, NO) + call ap_plot1 (gt, Memr[spec], ny, nsubaps) + } + + case ECHELLE: + do l = 1, nsubaps { + if (nsubaps == 1) + call strcpy (Memc[name], Memc[name1], SZ_LINE) + else { + call sprintf (Memc[name1], SZ_LINE, "%s%0*d") + call pargstr (Memc[name]) + call pargi (int(log10(real(nsubaps)))+1) + call pargi (l) + } + if (streq (Memc[input], Memc[name])) { + call strcat (".ec", Memc[name1], SZ_LINE) + call strcat (Memc[ksection], Memc[name1], SZ_LINE) + } + + if (iap == 1) { + out = immap (Memc[name1], NEW_COPY, in) + + IM_PIXTYPE(out) = TY_REAL + IM_NDIM(out) = 1 + IM_LEN(out, 1) = ny + IM_LEN(out, 2) = naps + IM_LEN(out, 3) = 1 + if (extras) { + if (sky != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + if (raw != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + if (sig != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + } + if (IM_LEN(out, 2) > 1) + IM_NDIM(out) = 2 + if (IM_LEN(out, 3) > 1) + IM_NDIM(out) = 3 + + apmw = apmw_open (in, out, dispaxis, naps, ny) + + # Write BAND IDs. + k = 1 + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "spectrum - background %s, weights %s, clean %s") + call pargstr (bkg) + call pargstr (wt) + call pargstr (clean) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + if (extras) { + if (raw != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "raw - background %s, weights none, clean no") + call pargstr (bkg) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + } + if (sky != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "background - background %s") + call pargstr (bkg) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + } + if (sig != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "sigma - background %s, weights %s, clean %s") + call pargstr (bkg) + call pargstr (wt) + call pargstr (clean) + call imastr (out, Memc[str1], Memc[str]) + } + } + + # Write keyword to allow matching by subaperture. + if (nsubaps > 1) + call imaddi (out, "SUBAP", l) + + do k = 1, naps { + low = AP_CEN(aps[k],apaxis) + AP_LOW(aps[k],apaxis) + high = AP_CEN(aps[k],apaxis) + AP_HIGH(aps[k],apaxis) + step = (high - low) / nsubaps + call apmw_setap (apmw, k, AP_ID(aps[k]), + AP_BEAM(aps[k]), low+(l-1)*step, low+l*step) + } + do k = 1, naps { + if (AP_TITLE(aps[k]) != NULL) { + call sprintf (Memc[str], SZ_LINE, "APID%d") + call pargi (k) + call imastr (out, Memc[str], + Memc[AP_TITLE(aps[k])]) + } + } + } else { + if (l == 1) + out = outsave + else + out = immap (Memc[name1], READ_WRITE, 0) + } + + k = iap + buf = impl2r (out, k) + call amovr (Memr[spec+(l-1)*ny], Memr[buf], ny) + if (extras) { + m = 2 + if (raw != NULL) { + buf = impl3r (out, k, m) + call amovr (Memr[raw+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + if (sky != NULL) { + buf = impl3r (out, k, m) + call amovr (Memr[sky+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + if (sig != NULL) { + buf = impl3r (out, k, m) + call amovr (Memr[sig+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + } + + if (iap == 1) { + call apmw_saveim (apmw, out, fmt) + call apmw_close (apmw) + } + if (l != 1 || iap == naps) + call imunmap (out) + if (l == 1) + outsave = out + + if (nsubaps == 1) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d from %s --> %s") + call pargi (AP_ID(ap)) + call pargstr (image) + call pargstr (Memc[name1]) + } else { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d-%d from %s --> %s") + call pargi (AP_ID(ap)) + call pargi (l) + call pargstr (image) + call pargstr (Memc[name1]) + } + call ap_log (Memc[str], YES, YES, NO) + } + + call ap_plot1 (gt, Memr[spec], ny, nsubaps) + + case ONEDSPEC: + do l = 1, nsubaps { + apid = AP_ID(ap) + (l - 1) * 1000 + low = AP_CEN(ap,apaxis) + AP_LOW(ap,apaxis) + high = AP_CEN(ap,apaxis) + AP_HIGH(ap,apaxis) + step = (high - low) / nsubaps + low = low + (l - 1) * step + high = low + step + + call sprintf (Memc[str], SZ_LINE, "%s.%0*d") + call pargstr (Memc[name]) + call pargi (int(log10(real(nsubaps)))+4) + call pargi (apid) + out = immap (Memc[str], NEW_COPY, in) + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d from %s --> %s.%0*d") + call pargi (apid) + call pargstr (image) + call pargstr (Memc[name]) + call pargi (int(log10(real(nsubaps)))+4) + call pargi (apid) + call ap_log (Memc[str], YES, YES, NO) + + apmw = apmw_open (in, out, dispaxis, 1, ny) + call apmw_setap (apmw, 1, apid, AP_BEAM(ap), low, high) + if (AP_TITLE(ap) != NULL) + call imastr (out, "APID1", Memc[AP_TITLE(ap)]) + + IM_PIXTYPE(out) = TY_REAL + IM_NDIM(out) = 1 + IM_LEN(out, 1) = ny + IM_LEN(out, 2) = 1 + IM_LEN(out, 3) = 1 + if (extras) { + if (sky != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + if (raw != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + if (sig != NULL) + IM_LEN(out, 3) = IM_LEN(out, 3) + 1 + } + if (IM_LEN(out, 2) > 1) + IM_NDIM(out) = 2 + if (IM_LEN(out, 3) > 1) + IM_NDIM(out) = 3 + + # Write BAND IDs. + k = 1 + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "spectrum: background %s, weights %s, clean %s") + call pargstr (bkg) + call pargstr (wt) + call pargstr (clean) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + if (extras) { + if (raw != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "spectrum: background %s, weights none, clean no") + call pargstr (bkg) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + } + if (sky != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "background: background %s") + call pargstr (bkg) + call imastr (out, Memc[str1], Memc[str]) + k = k + 1 + } + if (sig != NULL) { + call sprintf (Memc[str1], SZ_LINE, "BANDID%d") + call pargi (k) + call sprintf (Memc[str], SZ_LINE, + "sigma - background %s, weights %s, clean %s") + call pargstr (bkg) + call pargstr (wt) + call pargstr (clean) + call imastr (out, Memc[str1], Memc[str]) + } + } + + buf = impl2r (out, 1) + call amovr (Memr[spec+(l-1)*ny], Memr[buf], ny) + if (extras) { + m = 2 + if (raw != NULL) { + buf = impl3r (out, 1, m) + call amovr (Memr[raw+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + if (sky != NULL) { + buf = impl3r (out, 1, m) + call amovr (Memr[sky+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + if (sig != NULL) { + buf = impl3r (out, 1, m) + call amovr (Memr[sig+(l-1)*ny], Memr[buf], ny) + m = m + 1 + } + } + + call apmw_saveim (apmw, out, fmt) + call apmw_close (apmw) + call imunmap (out) + + } + + call ap_plot1 (gt, Memr[spec], ny, nsubaps) + + case STRIP: + do l = 1, nsubaps { + apid = AP_ID(ap) + (l - 1) * 1000 + low = AP_CEN(ap,apaxis) + AP_LOW(ap,apaxis) + high = AP_CEN(ap,apaxis) + AP_HIGH(ap,apaxis) + step = (high - low) / nsubaps + low = low + (l - 1) * step + high = low + step + + call sprintf (Memc[str], SZ_LINE, "%s.%0*d") + call pargstr (Memc[name]) + call pargi (int(log10(real(nsubaps)))+4) + call pargi (apid) + out = immap (Memc[str], NEW_COPY, in) + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d from %s --> %s.%0*d") + call pargi (apid) + call pargstr (image) + call pargstr (Memc[name]) + call pargi (int(log10(real(nsubaps)))+4) + call pargi (apid) + call ap_log (Memc[str], YES, YES, NO) + + apmw = apmw_open (in, out, dispaxis, 1, ny) + call apmw_setap (apmw, 1, apid, AP_BEAM(ap), low, high) + call sprintf (Memc[str], SZ_LINE, "%s - Aperture %d") + call pargstr (IM_TITLE(out)) + call pargi (AP_ID(ap)) + call strcpy (Memc[str], IM_TITLE(out), SZ_IMTITLE) + if (AP_TITLE(ap) != NULL) + call imastr (out, "APID1", Memc[AP_TITLE(ap)]) + + IM_PIXTYPE(out) = TY_REAL + IM_NDIM(out) = 2 + IM_LEN(out, 1) = ny + IM_LEN(out, 2) = high - low + 1 + + if (profile == NULL) + call ap_strip (ap, low, high, out, dbuf, nc, nl, c1, l1, + sbuf, nx, ny, xs, ys) + else + call ap_pstrip (ap, low, high, out, gain, Memr[spec], + Memr[profile], nx, ny, xs, ys) + + call apmw_saveim (apmw, out, fmt) + call apmw_close (apmw) + call imunmap (out) + } + + call ap_plot1 (gt, Memr[spec], ny, nsubaps) + + case NORM, FLAT: + if (iap == 1) { + out = immap (Memc[name], NEW_COPY, in) + IM_PIXTYPE(out) = TY_REAL + if (imaccf (out, "CCDMEAN") == YES) + call imdelf (out, "CCDMEAN") + call ap_fitspec (ap, in, Memr[spec], ny) + k = YES + } else { + call ap_fitspec (ap, in, Memr[spec], ny) + k = NO + } + if (apaxis == 1) { + if (fmt == NORM) + call ap_lnorm (ap, out, gain, dbuf, nc, nl, c1, l1, + Memr[spec], ny, ys, k) + else + call ap_lflat (ap, out, dbuf, nc, nl, c1, l1, Memr[spec], + sbuf, Memr[profile], nx, ny, xs, ys, k) + } else { + if (fmt == NORM) + call ap_cnorm (ap, out, gain, dbuf, nc, nl, c1, l1, + Memr[spec], ny, ys, k) + else + call ap_cflat (ap, out, dbuf, nc, nl, c1, l1, Memr[spec], + sbuf, Memr[profile], nx, ny, xs, ys, k) + } + if (iap == naps) + call imunmap (out) + + if (Memc[name] != EOS) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d from %s --> %s") + call pargi (AP_ID(ap)) + call pargstr (image) + call pargstr (Memc[name]) + call ap_log (Memc[str], YES, YES, NO) + call ap_plot1 (gt, Memr[spec], ny, nsubaps) + } + + case RATIO, FIT: + if (iap == 1) { + out = immap (Memc[name], NEW_COPY, in) + IM_PIXTYPE(out) = TY_REAL + k = YES + } else + k = NO + if (apaxis == 1) { + switch (fmt) { + case RATIO: + call ap_lflat (ap, out, dbuf, nc, nl, c1, l1, Memr[spec], + sbuf, Memr[profile], nx, ny, xs, ys, k) + case FIT: + call ap_lfit (ap, out, gain, Memr[spec], Memr[profile], + nx, ny, xs, ys, k) + } + } else { + switch (fmt) { + case RATIO: + call ap_cflat (ap, out, dbuf, nc, nl, c1, l1, Memr[spec], + sbuf, Memr[profile], nx, ny, xs, ys, k) + case FIT: + call ap_cfit (ap, out, gain, Memr[spec], Memr[profile], + nx, ny, xs, ys, k) + } + } + if (iap == naps) + call imunmap (out) + + if (Memc[name] != EOS) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d from %s --> %s") + call pargi (AP_ID(ap)) + call pargstr (image) + call pargstr (Memc[name]) + call ap_log (Memc[str], YES, YES, NO) + call ap_plot1 (gt, Memr[spec], ny, nsubaps) + } + + case DIFF: + if (iap == 1) { + out = immap (Memc[name], NEW_COPY, in) + IM_PIXTYPE(out) = TY_REAL + do k = 1, IM_LEN(in,2) { + buf = impl2r (out, k) + call amovr (Memr[imgl2r(in,k)], Memr[buf], IM_LEN(out,1)) + } + k = NO + } else + k = NO + if (apaxis == 1) + call ap_ldiff (ap, out, gain, dbuf, nc, nl, c1, l1, Memr[spec], + Memr[profile], nx, ny, xs, ys, k) + else + call ap_cdiff (ap, out, gain, dbuf, nc, nl, c1, l1, Memr[spec], + Memr[profile], nx, ny, xs, ys, k) + if (iap == naps) + call imunmap (out) + + if (Memc[name] != EOS) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d from %s --> %s") + call pargi (AP_ID(ap)) + call pargstr (image) + call pargstr (Memc[name]) + call ap_log (Memc[str], YES, YES, NO) + call ap_plot1 (gt, Memr[spec], ny, nsubaps) + } + + case NOISE: + if (iap == 1) { + low = clgetr ("dmin") + high = clgetr ("dmax") + l = clgetr ("nbins") + if (high < low) { + step = low; low = high; high = step + } + step = (high - low) / l + call malloc (sum2, l, TY_REAL) + call malloc (sum4, l, TY_REAL) + call malloc (nsum, l, TY_INT) + call aclrr (Memr[sum2], l) + call aclrr (Memr[sum4], l) + call aclri (Memi[nsum], l) + } + call ap_noise (ap, gain, dbuf, nc, nl, c1, l1, sbuf, Memr[spec], + Memr[profile], nx, ny, xs, ys, Memr[sum2], Memr[sum4], + Memi[nsum], l, low, high) + if (iap == naps) { + do k = 0, l-1 { + m = Memi[nsum+k] + if (m > 10) { + Memr[sum2+k] = sqrt (Memr[sum2+k] / (m - 1)) + step = max (0., Memr[sum4+k] / m - Memr[sum2+k]**2) + Memr[sum4+k] = sqrt (sqrt (step / m)) + } else { + Memr[sum2+k] = 0. + Memr[sum4+k] = 0. + } + } + call ap_nplot (image, in, Memr[sum2], Memr[sum4], l, + low, high) + call mfree (sum2, TY_REAL) + call mfree (sum4, TY_REAL) + call mfree (nsum, TY_INT) + } + + if (Memc[name] != EOS) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT - Aperture %d from %s --> %s") + call pargi (AP_ID(ap)) + call pargstr (image) + call pargstr (Memc[name]) + call ap_log (Memc[str], YES, YES, NO) + call ap_plot1 (gt, Memr[spec], ny, nsubaps) + } + } + + call gt_free (gt) + call sfree (sp) +end + + +# AP_SUM -- Simple, unweighted aperture sum. + +procedure ap_sum (ap, dbuf, nc, nl, c1, l1, sbuf, nx, ny, xs, ys, spec, + nsubaps, asi) + +pointer ap # Aperture structure +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +pointer sbuf # Sky values (NULL if none) +int nx, ny # Size of profile array +int xs[ny], ys # Origin of sky array +real spec[ny, nsubaps] # Spectrum +int nsubaps # Number of subapertures +pointer asi # Interpolator for edge pixel weighting + +int i, ix, iy, ix1, ix2 +real low, high, step, x1, x2, wt1, wt2, s, sval, skyval +real ap_cveval() +pointer cv, data, sky +errchk asifit + +begin + i = AP_AXIS(ap) + low = AP_CEN(ap,i) + AP_LOW(ap,i) + high = AP_CEN(ap,i) + AP_HIGH(ap,i) + step = (high - low) / nsubaps + cv = AP_CV(ap) + do iy = 1, ny { + s = ap_cveval (cv, real (iy + ys - 1)) - c1 + 1 + call ap_asifit (dbuf+(iy+ys-1-l1)*nc, nc, xs[iy]-c1+1, + low+s, high+s, data, asi) +# data = dbuf + (iy + ys - 1 - l1) * nc + xs[iy] - c1 - 1 +# if (asi != NULL) +# call asifit (asi, Memr[data], nc-xs[iy]+c1) + do i = 1, nsubaps { + x1 = max (0.5, low + (i - 1) * step + s) + c1 - xs[iy] + x2 = min (nc + 0.49, low + i * step + s) + c1 - xs[iy] + if (x2 <= x1) { + spec[iy,i] = 0. + next + } + ix1 = nint (x1) + ix2 = nint (x2) + + # Compute end pixel weights. Remember asi is offset by 1. + call ap_edge (asi, x1+1, x2+1, wt1, wt2) + + # Sum pixels. + sval = wt1 * Memr[data+ix1] + wt2 * Memr[data+ix2] + do ix = ix1+1, ix2-1 + sval = sval + Memr[data+ix] + + # Subtract sky if desired. + if (sbuf != NULL) { + sky = sbuf + (iy - 1) * nx - 1 + skyval = wt1 * Memr[sky+ix1] + wt2 * Memr[sky+ix2] + do ix = ix1+1, ix2-1 + skyval = skyval + Memr[sky+ix] + sval = sval - skyval + } + + # Save extracted pixel value. + spec[iy,i] = sval + } + } +end + + +# AP_EDGE -- Compute edge weights. + +procedure ap_edge (asi, x1, x2, wt1, wt2) + +pointer asi #I Image interpolator pointer +real x1, x2 #I Aperture edges +real wt1, wt2 #I Weights + +int ix1, ix2 +real a, b +real asieval(), asigrl() + +begin + # Edge pixel centers. + ix1 = nint (x1) + ix2 = nint (x2) + + # Default weights are fractions of pixel. + if (ix1 == ix2) { + wt1 = (x2 - x1) + wt2 = 0 + } else { + wt1 = (ix1 - x1 + 0.5) + wt2 = (x2 - ix2 + 0.5) + } + + # If there is an interpolator compute fraction of integral. + # We require that data and integrals be positive. + if (asi != NULL) { + if (asieval (asi, real(ix1)) > 0) { + b = asigrl (asi, ix1-0.5, ix1+0.5) + if (b > 0) { + if (ix1 == ix2) + a = asigrl (asi, x1, x2) + else + a = asigrl (asi, x1, ix1+0.5) + if (a > 0 && a < b) + wt1 = a / b + } + } + if (ix1 != ix2 && asieval (asi, real(ix2)) > 0) { + b = asigrl (asi, ix2-0.5, ix2+0.5) + if (b > 0) { + a = asigrl (asi, ix2-0.5, x2) + if (a > 0 && a < b) + wt2 = a / b + } + } + } +end + + +# AP_STRIP -- Simple, unweighted aperture strip. +# Interpolate so that the lower edge of the aperture is the first pixel. + +procedure ap_strip (ap, aplow, aphigh, out, dbuf, nc, nl, c1, l1, sbuf, nx, ny, + xs, ys) + +pointer ap # Aperture structure +real aplow, aphigh # Aperture limits +pointer out # Output IMIO pointer +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +pointer sbuf # Sky values (NULL if none) +int nx, ny # Size of profile array +int xs[ny], ys # Origin of sky array + +int i, na, iy, ix1, ix2, nasi +real low, high, s, x, ap_cveval(), asieval() +pointer obuf, cv, asi, data, sky, ptr, imps2r() + +begin + i = AP_AXIS(ap) + low = aplow - c1 + 1 + high = aphigh - c1 + 1 + cv = AP_CV(ap) + call asiinit (asi, II_LINEAR) + + na = IM_LEN(out,2) + obuf = imps2r (out, 1, ny, 1, na) + call aclrr (Memr[obuf], na * ny) + + do iy = 1, ny { + i = iy + ys - 1 + s = ap_cveval (cv, real (i)) + ix1 = max (1, nint (low + s) - 1) + ix2 = min (nc, nint (high + s) + 1) + nasi = ix2 - ix1 + 1 + if (nasi < 3) + next + data = dbuf + (i - l1) * nc + ix1 - 1 + iferr (call asifit (asi, Memr[data], nasi)) + next + + x = low + s - ix1 + 1 + ptr = obuf + iy - 1 + if (sbuf == NULL) { + do i = 1, na { + if (x >= 1 && x <= nasi) + Memr[ptr] = asieval (asi, x) + x = x + 1. + ptr = ptr + ny + } + } else { + sky = sbuf + (iy - 1) * nx + nint (low + s) - xs[iy] + c1 - 2 + do i = 1, na { + if (x >= 1 && x <= nasi) + Memr[ptr] = asieval (asi, x) - Memr[sky+i] + x = x + 1. + ptr = ptr + ny + } + } + } + + call asifree (asi) +end + + +# AP_PSTRIP -- Profile based strip. +# Interpolate the profile spectrum so that the lower aperture edge is the +# first pixel. + +procedure ap_pstrip (ap, aplow, aphigh, out, gain, spec, profile, nx, ny, + xs, ys) + +pointer ap # Aperture structure +real aplow, aphigh # Aperture limits +pointer out # Output IMIO pointer +real gain # Gain +real spec[ny] # Spectrum +real profile[ny,nx] # Profile +int nx, ny # Size of profile array +int xs[ny], ys # Origin of profile array + +int na, ix, iy +real low, high, s, x, ap_cveval(), asieval() +pointer sp, cv, asi, data, impl2r() + +begin + call smark (sp) + call salloc (data, nx, TY_REAL) + + ix = AP_AXIS(ap) + low = aplow + high = aphigh + cv = AP_CV(ap) + na = IM_LEN(out,2) + call asiinit (asi, II_LINEAR) + + do iy = 1, ny { + s = spec[iy] / gain + do ix = 1, nx + Memr[data+ix-1] = s * profile[iy,ix] + call asifit (asi, Memr[data], nx) + s = ap_cveval (cv, real (iy+ys-1)) - xs[iy] + 1 + x = low + s + do ix = 1, na { + profile[iy,ix] = asieval (asi, x) + x = x + 1 + } + } + + do ix = 1, na + call amovr (profile[1,ix], Memr[impl2r(out,ix)], ny) + + call asifree (asi) +end + + +# AP_ASIFIT -- Return interpolation pointer and data pointer. +# +# The main reason for this routine is to shift the origin of the data by +# one pixel so that the interpolator may be called to evaluate across +# the extent of the first and last pixels. This means the calling program +# will reference asi fit between 1.5 and N+1.5. It also means the returned +# data pointer may start before the first point but will never be +# dereferenced outside of the data range. + +procedure ap_asifit (dbuf, nc, xs, low, high, data, asi) + +pointer dbuf #I Data buffer pointer +int nc #I Size of data buffer +int xs #I Start of aperture array (in dbuf coords) +real low #I Low aperture edge (in dbuf coords) +real high #I High aperture edge (in dbuf coords) +pointer data #O Data pointer +pointer asi #I ASI pointer + +int i, ix1, ix2, n +real x1, x2 +pointer fit + +begin + # Check for in bounds data. + x1 = max (0.5, low) + x2 = min (nc + 0.49, high) + if (x1 >= x2) + return + + # Set data pointer relative to the aperture start with an offset for + # one indexing; i.e. pixel i is referenced as Memr[data+i]. The + # aperture start may put this outside the data buffer but we expect + # routines using the pointer to never index outside of the buffer. + + data = (dbuf + xs - 1) - 1 + + # If not using an interpolator we are done. + + if (asi == NULL) + return + + # If the aperture, with one extra pixel on each end for integration + # across the end pixel, is within the data buffer then fit an + # interpolator directly. Otherwise we need to use a temporary + # padded buffer. The origin of the fitted buffer is relative + # to the data pointer. Note that this means that evaluating the + # fit requires the aperture start coordinates to be incremented + # by 1. + + ix1 = 0 + ix2 = nint (x2) + 1 - (xs - 1) + n = ix2 + ix1 + 1 + if (data + ix1 >= dbuf && data + ix2 <= dbuf + nc - 1) { + call asifit (asi, Memr[data+ix1], n) + return + } + + # One or the other end point is out of bounds so to avoid potential + # NAN and segmentation errors use an internal array to pad. + + call malloc (fit, n, TY_REAL) + do i = 0, n-1 { + if (data + i < dbuf) + Memr[fit+i] = Memr[dbuf] + else if (data + i > dbuf + nc - 1) + Memr[fit+i] = Memr[dbuf+nc-1] + else + Memr[fit+i] = Memr[data+i] + } + call asifit (asi, Memr[fit], n) + call mfree (fit, TY_REAL) +end diff --git a/noao/twodspec/apextract/apfind.par b/noao/twodspec/apextract/apfind.par new file mode 100644 index 00000000..f879a4a7 --- /dev/null +++ b/noao/twodspec/apextract/apfind.par @@ -0,0 +1,18 @@ +# APFIND + +input,s,a,,,,List of input images +apertures,s,h,"",,,Apertures +references,s,h,"",,,"Reference images +" +interactive,b,h,no,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,no,,,Recenter apertures? +resize,b,h,no,,,Resize apertures? +edit,b,h,yes,,,"Edit apertures? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,1,,,Number of dispersion lines to sum or median +nfind,i,q,,,,Number of apertures to be found automatically +minsep,r,h,5.,1.,,Minimum separation between spectra +maxsep,r,h,1000.,1.,,Maximum separation between spectra +order,s,h,"increasing","increasing|decreasing",,Order of apertures diff --git a/noao/twodspec/apextract/apfind.x b/noao/twodspec/apextract/apfind.x new file mode 100644 index 00000000..f58dd4f4 --- /dev/null +++ b/noao/twodspec/apextract/apfind.x @@ -0,0 +1,132 @@ +include <imhdr.h> +include <mach.h> +include "apertures.h" + +# Sort flags +define ORDER "|increasing|decreasing|" + +# AP_FIND -- Find and set apertures automatically. + +procedure ap_find (image, line, nsum, aps, naps) + +char image[SZ_FNAME] # Image name +int line # Image dispersion line +int nsum # Number of dispersion lines to sum +pointer aps # Aperture pointers +int naps # Number of apertures + +real minsep, center +int i, j, npts, apaxis, nfind, nx +pointer im, imdata, title, sp, str, x, ids + +bool clgetb(), ap_answer() +int apgeti(), apgwrd() +real apgetr(), ap_center(), ap_cveval() + +errchk ap_getdata, ap_default + +begin + # Find apertures only if there are no other apertures defined. + if (naps != 0) + return + + # Query user. + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call sprintf (Memc[str], SZ_LINE, "Find apertures for %s?") + call pargstr (image) + if (!ap_answer ("ansfind", Memc[str])) { + call sfree (sp) + return + } + + if (clgetb ("verbose")) + call printf ("Finding apertures ...\n") + + # Get CL parameters. + nfind = apgeti ("nfind") + if (nfind == 0) + return + minsep = apgetr ("minsep") + + # Map the image and get the image data. + call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, title) + + # If nfind > 0 find the peaks. Otherwise divide the image evenly + # into apertures. + + if (nfind > 0) { + # Allocate working memory. + call salloc (x, nfind+2, TY_REAL) + + # Find the peaks. + nx = 0 + call find_peaks (Memr[imdata], npts, 0., 1, nfind+2, minsep, + -MAX_REAL, Memr[x], nx) + #call find_peaks (Memr[imdata], npts, 0., 1, nfind+2, minsep, + # 0, Memr[x], nx) + #call asrtr (Memr[x], Memr[x], nx) + + # Center on the peaks. + naps = 0 + for (i = 1; i <= nx && naps < nfind; i = i + 1) { + center = Memr[x+i-1] + center = ap_center (center, Memr[imdata], npts) + + if (!IS_INDEF(center)) { + if (mod (naps, 100) == 0) + call realloc (aps, naps+100, TY_POINTER) + if (naps == 0) + call ap_default (im, INDEFI, 1, apaxis, INDEFR, + real (line), Memi[aps+naps]) + else + call ap_copy (Memi[aps], Memi[aps+naps]) + + AP_CEN(Memi[aps+naps], AP_AXIS(Memi[aps+naps])) = center - + ap_cveval (AP_CV(Memi[aps+naps]), real (line)) + naps = naps + 1 + } + } + + } else { + nfind = abs (nfind) + minsep = real (npts) / nfind + naps = 0 + do i = 1, nfind { + if (mod (naps, 100) == 0) + call realloc (aps, naps+100, TY_POINTER) + center = (i - 0.5) * minsep + IF (naps == 0) + call ap_default (im, INDEFI, 1, apaxis, INDEFR, + real (line), Memi[aps+naps]) + else + call ap_copy (Memi[aps], Memi[aps+naps]) + + AP_CEN(Memi[aps+naps], AP_AXIS(Memi[aps+naps])) = center - + ap_cveval (AP_CV(Memi[aps+naps]), real (line)) + naps = naps + 1 + } + } + + # Set the aperture ID's + i = apgwrd ("order", Memc[str], SZ_LINE, ORDER) + call ap_sort (j, Memi[aps], naps, i) + call ap_gids (ids) + call ap_ids (Memi[aps], naps, ids) + call ap_titles (Memi[aps], naps, ids) + call ap_fids (ids) + + # Log the apertures found and write them to the database. + call sprintf (Memc[str], SZ_LINE, "FIND - %d apertures found for %s") + call pargi (naps) + call pargstr (image) + call ap_log (Memc[str], YES, YES, NO) + + call appstr ("ansdbwrite1", "yes") + + # Free memory and unmap the image. + call mfree (imdata, TY_REAL) + call mfree (title, TY_CHAR) + call imunmap (im) + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apfindnew.x b/noao/twodspec/apextract/apfindnew.x new file mode 100644 index 00000000..66762f78 --- /dev/null +++ b/noao/twodspec/apextract/apfindnew.x @@ -0,0 +1,83 @@ +include <mach.h> +include "apertures.h" + +# Sort flags +define ORDER "|increasing|decreasing|" + +# AP_FINDNEW -- Find and set new apertures automatically. This task is +# called from the aperture editor so we don't want to read the image vector +# again. It also differs from AP_FIND in that existing apertures are +# maintained and new apertures are added. + +procedure ap_findnew (line, data, npts, apdef, aps, naps) + +int line # Dispersion line of data +real data[npts] # Image data in which to find features +int npts # Number of pixels +pointer apdef # Default aperture pointer +pointer aps # Aperture pointers +int naps # Number of apertures returned + +int i, j, nx, nfind +real center, minsep +pointer sp, str, x, ids + +bool clgetb() +int apgeti(), apgwrd() +real apgetr(), ap_center(), ap_cveval() + +begin + # Determine the maximum number of apertures to be found and return + # if that limit has been reached. + nfind = apgeti ("nfind") + if (nfind <= naps) + return + + if (clgetb ("verbose")) + call printf ("Finding apertures ...\n") + + # Set the positions of the currently defined apertures. + call smark (sp) + call salloc (str, SZ_FNAME, TY_CHAR) + call salloc (x, max (nfind, naps), TY_REAL) + nx = naps + for (i = 0; i < nx; i = i + 1) + Memr[x+i] = AP_CEN (Memi[aps+i], AP_AXIS(Memi[aps+i])) + + ap_cveval (AP_CV(Memi[aps+i]), real (line)) + + # Find peaks not already identified. + minsep = apgetr ("minsep") + #call find_peaks (data, npts, 0., 1, nfind, minsep, 0., Memr[x], nx) + call find_peaks (data, npts, 0., 1, nfind, minsep, -MAX_REAL, + Memr[x], nx) + call asrtr (Memr[x+naps], Memr[x+naps], nx - naps) + + # Center on the new peaks and define new apertures. + for (i = naps + 1; i <= nx; i = i + 1) { + center = Memr[x+i-1] + center = ap_center (center, data, npts) + + if (!IS_INDEF(center)) { + if (mod (naps, 100) == 0) + call realloc (aps, naps+100, TY_POINTER) + + call ap_copy (apdef, Memi[aps+naps]) + + AP_ID(Memi[aps+naps]) = INDEFI + if (AP_TITLE(Memi[aps+naps]) != NULL) + call mfree (AP_TITLE(Memi[aps+naps]), TY_CHAR) + AP_CEN(Memi[aps+naps], AP_AXIS(Memi[aps+naps])) = center - + ap_cveval (AP_CV(Memi[aps+naps]), real (line)) + naps = naps + 1 + } + } + + # Set the aperture ID's + i = apgwrd ("order", Memc[str], SZ_LINE, ORDER) + call ap_sort (j, Memi[aps], naps, i) + call ap_gids (ids) + call ap_ids (Memi[aps], naps, ids) + call ap_titles (Memi[aps], naps, ids) + call ap_fids (ids) + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apfit.par b/noao/twodspec/apextract/apfit.par new file mode 100644 index 00000000..1d6da386 --- /dev/null +++ b/noao/twodspec/apextract/apfit.par @@ -0,0 +1,30 @@ +# APFIT + +input,s,a,,,,List of images to fit +output,s,a,,,,List of output images +apertures,s,h,"",,,Apertures +fittype,s,a,"difference","fit|difference|ratio",,Type of output fit +references,s,h,"",,,"List of reference images +" +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,yes,,,Recenter apertures? +resize,b,h,yes,,,Resize apertures? +edit,b,h,yes,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,Fit traced points interactively? +fit,b,h,yes,,,"Fit apertures? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,10,,,Number of dispersion lines to sum or median +threshold,r,h,10.,,,"Division threshold for ratio fit +" +background,s,h,"none","none|average|median|minimum|fit",,Background to subtract +pfit,s,h,"fit1d","fit1d|fit2d",,Profile fitting type (fit1d|fit2d) +clean,b,h,no,,,Detect and replace bad pixels? +skybox,i,h,1,1,,Box car smoothing length for sky +saturation,r,h,INDEF,,,Saturation level +readnoise,s,h,"0.",,,Read out noise sigma (photons) +gain,s,h,"1.",,,Photon gain (photons/data number) +lsigma,r,h,4.,0.,,Lower rejection threshold +usigma,r,h,4.,0.,,Upper rejection threshold diff --git a/noao/twodspec/apextract/apfit.x b/noao/twodspec/apextract/apfit.x new file mode 100644 index 00000000..67bf149d --- /dev/null +++ b/noao/twodspec/apextract/apfit.x @@ -0,0 +1,737 @@ +include <imhdr.h> +include <imset.h> +include <pkg/gtools.h> +include "apertures.h" + + +# AP_FITSPEC -- Fit a spectrum by a smoothing function. + +procedure ap_fitspec (ap, in, spec, ny) + +pointer ap # Aperture (used for labels) +pointer in # Input image (used for labels) +real spec[ny] # spectrum +int ny # Number of points in spectra + +int i, fd, apaxis, clgeti() +real clgetr() +pointer sp, str, x, wts, cv, gp, gt, ic, ic1, gt_init() +bool ap_answer() +data ic1 /NULL/ +errchk icg_fit, ic_fit + +common /apn_com/ ic, gt + +begin + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (x, ny, TY_REAL) + call salloc (wts, ny, TY_REAL) + + do i = 1, ny { + Memr[x+i-1] = i + Memr[wts+i-1] = 1 + } + + if (ic == NULL || ic1 == NULL) { + call ic_open (ic) + ic1 = ic + call clgstr ("function", Memc[str], SZ_LINE) + call ic_pstr (ic, "function", Memc[str]) + call ic_puti (ic, "order", clgeti ("order")) + call clgstr ("sample", Memc[str], SZ_LINE) + call ic_pstr (ic, "sample", Memc[str]) + call ic_puti (ic, "naverage", clgeti ("naverage")) + call ic_puti (ic, "niterate", clgeti ("niterate")) + call ic_putr (ic, "low", clgetr ("low_reject")) + call ic_putr (ic, "high", clgetr ("high_reject")) + call ic_putr (ic, "grow", clgetr ("grow")) + call ic_pstr (ic, "ylabel", "") + + gt = gt_init() + } + + call ic_putr (ic, "xmin", 1.) + call ic_putr (ic, "xmax", real (ny)) + apaxis = AP_AXIS(ap) + switch (apaxis) { + case 1: + call ic_pstr (ic, "xlabel", "Line") + case 2: + call ic_pstr (ic, "xlabel", "Column") + } + call gt_sets (gt, GTTYPE, "line") + + # Fit spectrum by a smoothing function. + call sprintf (Memc[str], SZ_LINE, + "%s: %s - Aperture %s") + call pargstr (IM_HDRFILE(in)) + call pargstr (IM_TITLE(in)) + call pargi (AP_ID(ap)) + call gt_sets (gt, GTTITLE, Memc[str]) + + # Query the user to fit the spectrum interactively. + call sprintf (Memc[str], SZ_LINE, + "Fit spectrum for aperture %d for %s interactively?") + call pargi (AP_ID(ap)) + call pargstr (IM_HDRFILE(in)) + if (ap_answer ("ansfitspec1", Memc[str])) { + call ap_gopen (gp) + call icg_fit (ic, gp, "gcur", gt, cv, Memr[x], spec, + Memr[wts], ny) + call amovkr (1., Memr[wts], ny) + } else + call ic_fit (ic, cv, Memr[x], spec, Memr[wts], ny, + YES, YES, YES, YES) + + # Make a graph to the plot log. + call ap_popen (gp, fd, "fitspec") + if (gp != NULL) { + call icg_graphr (ic, gp, gt, cv, Memr[x], spec, Memr[wts], ny) + call ap_pclose (gp, fd) + } + + call cvvector (cv, Memr[x], spec, ny) + call cvfree (cv) +end + + +procedure ap_fitfree () + +pointer ic, gt +common /apn_com/ ic, gt + +begin + call ic_closer (ic) + call gt_free (gt) +end + + +# AP_LNORM -- Normalize the input line apertures by the norm spectra. + +procedure ap_lnorm (ap, out, gain, dbuf, nc, nl, c1, l1, spec, ny, ys, init) + +pointer ap # Aperture structure +pointer out # Output IMIO pointer +real gain # Gain +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real spec[ny] # Normalization spectrum +int ny # Size of profile array +int ys # Start of spectrum in image +int init # Fill between apertures with 1? + +bool clgetb() # Center normalize? +real threshold, clgetr() # Division threshold + +int i, ncols, nlines, ix1, ix2, iy, nsum +real cen, low, high, s, x1, x2, sum, ap_cveval(), asumr() +pointer cv, datain, dataout, imps2r(), impl2r() + +begin + threshold = clgetr ("threshold") + + cen = AP_CEN(ap,1) + low = AP_CEN(ap,1) + AP_LOW(ap,1) + high = AP_CEN(ap,1) + AP_HIGH(ap,1) + cv = AP_CV(ap) + ncols = IM_LEN(out, 1) + nlines = IM_LEN(out, 2) + + # Normalize by the aperture width and apply threshold. + call adivkr (spec, high - low, spec, ny) + if (clgetb ("cennorm")) { + sum = 0. + nsum = 0 + do i = 1, nlines { + iy = i - ys + 1 + if (iy < 1 || iy > ny) + next + s = cen + ap_cveval (cv, real (i)) + ix1 = max (1, int (s)) + ix2 = min (ncols, int (s + 1)) + if (ix1 > ix2) + next + datain = dbuf + (i - l1) * nc + ix1 - c1 + if (ix1 == ix2) + sum = sum + Memr[datain] + else + sum = sum + (ix2-s)*Memr[datain] + (s-ix1)*Memr[datain+1] + nsum = nsum + 1 + } + if (nsum > 0) { + sum = (asumr (spec, ny) / ny) / (sum / nsum / gain) + call adivkr (spec, sum, spec, ny) + } + } + if (!IS_INDEF (threshold)) + call arltr (spec, ny, threshold, threshold) + + do i = 1, nlines { + if (init == YES) { + dataout = impl2r (out, i) + call amovkr (1., Memr[dataout], ncols) + } + + iy = i - ys + 1 + if (iy < 1 || iy > ny) + next + s = ap_cveval (cv, real (i)) + x1 = max (0.5, low + s) + x2 = min (ncols + 0.49, high + s) + if (x1 > x2) + next + + ix1 = nint (x1) + ix2 = nint (x2) + + datain = dbuf + (i - l1) * nc + ix1 - c1 + if (init == YES) + dataout = dataout + ix1 - 1 + else + dataout = imps2r (out, ix1, ix2, i, i) + call adivkr (Memr[datain], spec[iy] * gain, Memr[dataout], + ix2-ix1+1) + } + + call imaddr (out, "CCDMEAN", 1.) +end + + +# AP_CNORM -- Normalize the input column apertures by the norm spectra. + +procedure ap_cnorm (ap, out, gain, dbuf, nc, nl, c1, l1, spec, ny, ys, init) + +pointer ap # Aperture structure +pointer out # Output IMIO pointer +real gain # Gain +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real spec[ny] # Normalization spectrum +int ny # Size of profile array +int ys # Start of spectrum in image +int init # Fill between apertures with 1? + +bool clgetb() # Center normalize? +real threshold, clgetr() # Division threshold + +int ncols, nlines, ix, iy, ix1, ix2, iy1, iy2, nsum +real cen, low, high, s, sum, ap_cveval(), asumr() +pointer sp, y1, y2, cv, datain, dataout, buf, imps2r(), impl2r() + +begin + threshold = clgetr ("threshold") + + call smark (sp) + call salloc (y1, 2 * ny, TY_INT) + y1 = y1 - ys + y2 = y1 + ny + + cen = AP_CEN(ap,2) + low = AP_CEN(ap,2) + AP_LOW(ap,2) + high = AP_CEN(ap,2) + AP_HIGH(ap,2) + cv = AP_CV(ap) + ncols = IM_LEN(out, 1) + nlines = IM_LEN(out, 2) + + # Normalize by the aperture width and apply threshold. + call adivkr (spec, high - low, spec, ny) + if (clgetb ("cennorm")) { + sum = 0. + nsum = 0 + do ix = ys, ys+ny-1 { + s = cen + ap_cveval (cv, real (ix)) + iy1 = max (1, int (s)) + iy2 = min (nlines, int (s + 1)) + if (iy1 > iy2) + next + datain = dbuf + (ix - l1) * nc + iy1 - c1 + if (iy1 == iy2) + sum = sum + Memr[datain] + else + sum = sum + (iy2-s)*Memr[datain] + (s-iy1)*Memr[datain+1] + nsum = nsum + 1 + } + if (nsum > 0) { + sum = (asumr (spec, ny) / ny) / (sum / nsum / gain) + call adivkr (spec, sum, spec, ny) + } + } + if (!IS_INDEF (threshold)) + call arltr (spec, ny, threshold, threshold) + + do ix = ys, ys+ny-1 { + s = ap_cveval (cv, real (ix)) + Memi[y1+ix] = nint (low + s) + Memi[y2+ix] = nint (high + s) + } + call alimi (Memi[y1+ys], 2 * ny, iy1, iy2) + + do iy = 1, nlines { + if (init == YES) { + buf = impl2r (out, iy) + call amovkr (1., Memr[buf], ncols) + } + + if (iy < iy1 || iy > iy2) + next + + for (ix1=ys; ix1<=ys+ny-1; ix1=ix1+1) { + if (iy < Memi[y1+ix1] || iy > Memi[y2+ix1]) + next + for (ix2=ix1+1; ix2<=ys+ny-1; ix2=ix2+1) + if (iy < Memi[y1+ix2] || iy > Memi[y2+ix2]) + break + ix2 = ix2 - 1 + + datain = dbuf + (ix1 - l1) * nc + iy - c1 + if (init == YES) + dataout = buf + ix1 - 1 + else + dataout = imps2r (out, ix1, ix2, iy, iy) + do ix = ix1, ix2 { + Memr[dataout] = Memr[datain] / spec[ix-ys+1] / gain + datain = datain + nc + dataout = dataout + 1 + } + ix1 = ix2 + } + } + + call imaddr (out, "CCDMEAN", 1.) + + call sfree (sp) +end + + +# AP_LFLAT -- Flatten the input line apertures by the norm spectra. + +procedure ap_lflat (ap, out, dbuf, nc, nl, c1, l1, spec, sbuf, profile, nx, ny, + xs, ys, init) + +pointer ap # Aperture structure +pointer out # Output IMIO pointer +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real spec[ny] # Normalization spectrum +pointer sbuf # Sky buffer +real profile[ny,nx] # Profile +int nx, ny # Size of profile array +int xs[ny], ys # Start of spectrum in image +int init # Fill between apertures with 1? + +real threshold, clgetr() # Division threshold + +int i, ncols, nlines, ix, iy, ix1, ix2 +real low, high, s, x1, x2, ap_cveval() +pointer cv, datain, dataout, sky, imps2r(), impl2r() + +begin + threshold = clgetr ("threshold") + if (IS_INDEF(threshold)) + threshold = 0. + threshold = max (0., threshold) + + low = AP_CEN(ap,1) + AP_LOW(ap,1) + high = AP_CEN(ap,1) + AP_HIGH(ap,1) + cv = AP_CV(ap) + ncols = IM_LEN(out, 1) + nlines = IM_LEN(out, 2) + + do i = 1, nlines { + if (init == YES) { + dataout = impl2r (out, i) + call amovkr (1., Memr[dataout], ncols) + } + + iy = i - ys + 1 + if (iy < 1 || iy > ny) + next + s = ap_cveval (cv, real (i)) + x1 = max (0.5, low + s) + x2 = min (ncols + 0.49, high + s) + if (x1 > x2) + next + + ix1 = nint (x1) + ix2 = nint (x2) + + datain = dbuf + (i - l1) * nc + ix1 - c1 + if (init == YES) + dataout = dataout + ix1 - 1 + else + dataout = imps2r (out, ix1, ix2, i, i) + if (sbuf != NULL) + sky = sbuf + (iy - 1) * nx - xs[iy] + do ix = ix1, ix2 { + s = spec[iy] * profile[iy, ix-xs[iy]+1] + if (sbuf != NULL) + s = s + Memr[sky+ix] + if (s > threshold) + Memr[dataout] = Memr[datain] / s + else + Memr[dataout] = 1. + datain = datain + 1 + dataout = dataout + 1 + } + } + + call imaddr (out, "CCDMEAN", 1.) +end + + +# AP_CFLAT -- Flatten the input column apertures by the norm spectra. + +procedure ap_cflat (ap, out, dbuf, nc, nl, c1, l1, spec, sbuf, profile, nx, ny, + xs, ys, init) + +pointer ap # Aperture structure +pointer out # Output IMIO pointer +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real spec[ny] # Normalization spectrum +pointer sbuf # Sky buffer +real profile[ny,nx] # Profile +int nx, ny # Size of profile array +int xs[ny], ys # Start of spectrum in image +int init # Fill between apertures with 1? + +real threshold, clgetr() # Division threshold + +int ncols, nlines, ix, iy, ix1, ix2, iy1, iy2 +real low, high, s, ap_cveval() +pointer sp, y1, y2, cv, datain, dataout, sky, buf, imps2r(), impl2r() + +begin + threshold = clgetr ("threshold") + if (IS_INDEF(threshold)) + threshold = 0. + threshold = max (0., threshold) + + call smark (sp) + call salloc (y1, 2 * ny, TY_INT) + y1 = y1 - ys + y2 = y1 + ny + + low = AP_CEN(ap,2) + AP_LOW(ap,2) + high = AP_CEN(ap,2) + AP_HIGH(ap,2) + cv = AP_CV(ap) + ncols = IM_LEN(out, 1) + nlines = IM_LEN(out, 2) + + do ix = ys, ys+ny-1 { + s = ap_cveval (cv, real (ix)) + Memi[y1+ix] = nint (low + s) + Memi[y2+ix] = nint (high + s) + } + call alimi (Memi[y1+ys], 2 * ny, iy1, iy2) + + do iy = 1, nlines { + if (init == YES) { + buf = impl2r (out, iy) + call amovkr (1., Memr[buf], ncols) + } + + if (iy < iy1 || iy > iy2) + next + + for (ix1=ys; ix1<=ys+ny-1; ix1=ix1+1) { + if (iy < Memi[y1+ix1] || iy > Memi[y2+ix1]) + next + for (ix2=ix1+1; ix2<=ys+ny-1; ix2=ix2+1) + if (iy < Memi[y1+ix2] || iy > Memi[y2+ix2]) + break + ix2 = ix2 - 1 + + datain = dbuf + (ix1 - l1) * nc + iy - c1 + if (init == YES) + dataout = buf + ix1 - 1 + else + dataout = imps2r (out, ix1, ix2, iy, iy) + if (sbuf != NULL) + sky = sbuf - ys * nx + iy - xs[iy] + do ix = ix1, ix2 { + s = spec[ix-ys+1] * profile[ix-ys+1, iy-xs[ix-ys+1]+1] + if (sbuf != NULL) + s = s + Memr[sky+ix*nx] + if (s > threshold) + Memr[dataout] = Memr[datain] / s + else + Memr[dataout] = 1. + datain = datain + nc + dataout = dataout + 1 + } + ix1 = ix2 + } + } + + call imaddr (out, "CCDMEAN", 1.) + + call sfree (sp) +end + + +# AP_LDIFF -- Model residuals. + +procedure ap_ldiff (ap, out, gain, dbuf, nc, nl, c1, l1, spec, profile, nx, ny, + xs, ys, init) + +pointer ap # Aperture structure +pointer out # Output IMIO pointer +real gain # Gain +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real spec[ny] # Normalization spectrum +real profile[ny,nx] # Profile +int nx, ny # Size of profile array +int xs[ny], ys # Start of spectrum in image +int init # Fill between apertures with 1? + +int i, ncols, nlines, ix, iy, ix1, ix2 +real low, high, s, x1, x2, ap_cveval() +pointer cv, datain, dataout, imps2r(), impl2r() + +begin + low = AP_CEN(ap,1) + AP_LOW(ap,1) + high = AP_CEN(ap,1) + AP_HIGH(ap,1) + cv = AP_CV(ap) + ncols = IM_LEN(out, 1) + nlines = IM_LEN(out, 2) + + do i = 1, nlines { + if (init == YES) { + dataout = impl2r (out, i) + call aclrr (Memr[dataout], ncols) + } + + iy = i - ys + 1 + if (iy < 1 || iy > ny) + next + s = ap_cveval (cv, real (i)) + x1 = max (0.5, low + s) + x2 = min (ncols + 0.49, high + s) + if (x1 > x2) + next + + ix1 = nint (x1) + ix2 = nint (x2) + + datain = dbuf + (i - l1) * nc + ix1 - c1 + if (init == YES) + dataout = dataout + ix1 - 1 + else + dataout = imps2r (out, ix1, ix2, i, i) + do ix = ix1, ix2 { + s = spec[iy] * profile[iy, ix-xs[iy]+1] + Memr[dataout] = (Memr[datain] - s) / gain + datain = datain + 1 + dataout = dataout + 1 + } + } +end + + +# AP_CDIFF -- Model residuals + +procedure ap_cdiff (ap, out, gain, dbuf, nc, nl, c1, l1, spec, profile, nx, ny, + xs, ys, init) + +pointer ap # Aperture structure +pointer out # Output IMIO pointer +real gain # Gain +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real spec[ny] # Normalization spectrum +real profile[ny,nx] # Profile +int nx, ny # Size of profile array +int xs[ny], ys # Start of spectrum in image +int init # Fill between apertures with 1? + +int ncols, nlines, ix, iy, ix1, ix2, iy1, iy2 +real low, high, s, ap_cveval() +pointer sp, y1, y2, cv, datain, dataout, buf, imps2r(), impl2r() + +begin + call smark (sp) + call salloc (y1, 2 * ny, TY_INT) + y1 = y1 - ys + y2 = y1 + ny + + low = AP_CEN(ap,2) + AP_LOW(ap,2) + high = AP_CEN(ap,2) + AP_HIGH(ap,2) + cv = AP_CV(ap) + ncols = IM_LEN(out, 1) + nlines = IM_LEN(out, 2) + + do ix = ys, ys+ny-1 { + s = ap_cveval (cv, real (ix)) + Memi[y1+ix] = nint (low + s) + Memi[y2+ix] = nint (high + s) + } + call alimi (Memi[y1+ys], 2 * ny, iy1, iy2) + + do iy = 1, nlines { + if (init == YES) { + buf = impl2r (out, iy) + call aclrr (Memr[buf], ncols) + } + + if (iy < iy1 || iy > iy2) + next + + for (ix1=ys; ix1<=ys+ny-1; ix1=ix1+1) { + if (iy < Memi[y1+ix1] || iy > Memi[y2+ix1]) + next + for (ix2=ix1+1; ix2<=ys+ny-1; ix2=ix2+1) + if (iy < Memi[y1+ix2] || iy > Memi[y2+ix2]) + break + ix2 = ix2 - 1 + + datain = dbuf + (ix1 - l1) * nc + iy - c1 + if (init == YES) + dataout = buf + ix1 - 1 + else + dataout = imps2r (out, ix1, ix2, iy, iy) + do ix = ix1, ix2 { + s = spec[ix-ys+1] * profile[ix-ys+1, iy-xs[ix-ys+1]+1] + Memr[dataout] = (Memr[datain] - s) / gain + datain = datain + nc + dataout = dataout + 1 + } + ix1 = ix2 + } + } + + call sfree (sp) +end + + +# AP_LFIT -- Model fit + +procedure ap_lfit (ap, out, gain, spec, profile, nx, ny, xs, ys, init) + +pointer ap # Aperture structure +pointer out # Output IMIO pointer +real gain # Gain +real spec[ny] # Normalization spectrum +real profile[ny,nx] # Profile +int nx, ny # Size of profile array +int xs[ny], ys # Start of spectrum in image +int init # Fill between apertures with 1? + +int i, ncols, nlines, ix, iy, ix1, ix2 +real low, high, s, x1, x2, ap_cveval() +pointer cv, dataout, imps2r(), impl2r() + +begin + low = AP_CEN(ap,1) + AP_LOW(ap,1) + high = AP_CEN(ap,1) + AP_HIGH(ap,1) + cv = AP_CV(ap) + ncols = IM_LEN(out, 1) + nlines = IM_LEN(out, 2) + + do i = 1, nlines { + if (init == YES) { + dataout = impl2r (out, i) + call aclrr (Memr[dataout], ncols) + } + + iy = i - ys + 1 + if (iy < 1 || iy > ny) + next + s = ap_cveval (cv, real (i)) + x1 = max (0.5, low + s) + x2 = min (ncols + 0.49, high + s) + if (x1 > x2) + next + + ix1 = nint (x1) + ix2 = nint (x2) + + if (init == YES) + dataout = dataout + ix1 - 1 + else + dataout = imps2r (out, ix1, ix2, i, i) + do ix = ix1, ix2 { + s = spec[iy] * profile[iy, ix-xs[iy]+1] + Memr[dataout] = s / gain + dataout = dataout + 1 + } + } +end + + +# AP_CFIT -- Model fit + +procedure ap_cfit (ap, out, gain, spec, profile, nx, ny, xs, ys, init) + +pointer ap # Aperture structure +pointer out # Output IMIO pointer +real gain # Gain +real spec[ny] # Normalization spectrum +real profile[ny,nx] # Profile +int nx, ny # Size of profile array +int xs[ny], ys # Start of spectrum in image +int init # Fill between apertures with 1? + +int ncols, nlines, ix, iy, ix1, ix2, iy1, iy2 +real low, high, s, ap_cveval() +pointer sp, y1, y2, cv, dataout, buf, imps2r(), impl2r() + +begin + call smark (sp) + call salloc (y1, 2 * ny, TY_INT) + y1 = y1 - ys + y2 = y1 + ny + + low = AP_CEN(ap,2) + AP_LOW(ap,2) + high = AP_CEN(ap,2) + AP_HIGH(ap,2) + cv = AP_CV(ap) + ncols = IM_LEN(out, 1) + nlines = IM_LEN(out, 2) + + do ix = ys, ys+ny-1 { + s = ap_cveval (cv, real (ix)) + Memi[y1+ix] = nint (low + s) + Memi[y2+ix] = nint (high + s) + } + call alimi (Memi[y1+ys], 2 * ny, iy1, iy2) + + do iy = 1, nlines { + if (init == YES) { + buf = impl2r (out, iy) + call aclrr (Memr[buf], ncols) + } + + if (iy < iy1 || iy > iy2) + next + + for (ix1=ys; ix1<=ys+ny-1; ix1=ix1+1) { + if (iy < Memi[y1+ix1] || iy > Memi[y2+ix1]) + next + for (ix2=ix1+1; ix2<=ys+ny-1; ix2=ix2+1) + if (iy < Memi[y1+ix2] || iy > Memi[y2+ix2]) + break + ix2 = ix2 - 1 + + if (init == YES) + dataout = buf + ix1 - 1 + else + dataout = imps2r (out, ix1, ix2, iy, iy) + do ix = ix1, ix2 { + s = spec[ix-ys+1] * profile[ix-ys+1, iy-xs[ix-ys+1]+1] + Memr[dataout] = s / gain + dataout = dataout + 1 + } + ix1 = ix2 + } + } + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apfit1.par b/noao/twodspec/apextract/apfit1.par new file mode 100644 index 00000000..5420917d --- /dev/null +++ b/noao/twodspec/apextract/apfit1.par @@ -0,0 +1,118 @@ +# OUTPUT PARAMETERS + +apertures,s,h,)apall.apertures,,,>apfit.apertures +format,s,h,)apsum.format,,,>apsum.format +extras,b,h,)apsum.extras,,,>apsum.extras +dbwrite,s,h,yes,,,Write to database? +initialize,b,h,yes,,,Initialize answers? +verbose,b,h,)_.verbose,,,"Verbose output? + +# DEFAULT APERTURE PARAMETERS +" +lower,r,h,)apdefault.lower,,,>apdefault.lower +upper,r,h,)apdefault.upper,,,>apdefault.upper +apidtable,s,h,)apdefault.apidtable,,,">apdefault.apidtable + +# DEFAULT BACKGROUND PARAMETERS +" +b_function,s,h,)apdefault.b_function,,,>apdefault.b_function +b_order,i,h,)apdefault.b_order,,,>apdefault.b_order +b_sample,s,h,)apdefault.b_sample,,,>apdefault.b_sample +b_naverage,i,h,)apdefault.b_naverage,,,>apdefault.b_naverage +b_niterate,i,h,)apdefault.b_niterate,,,>apdefault.b_niterate +b_low_reject,r,h,)apdefault.b_low_reject,,,>apdefault.b_low_reject +b_high_reject,r,h,)apdefault.b_high_reject,,,>apdefault.b_high_reject +b_grow,r,h,)apdefault.b_grow,,,">apdefault.b_grow + +# APERTURE CENTERING PARAMETERS +" +width,r,h,)apedit.width,,,>apedit.width +radius,r,h,)apedit.radius,,,>apedit.radius +threshold,r,h,)apedit.threshold,,,">apedit.threshold + +# AUTOMATIC FINDING AND ORDERING PARAMETERS +" +nfind,i,h,)apfind.nfind,,,>apfind.nfind +minsep,r,h,)apfind.minsep,,,>apfind.minsep +maxsep,r,h,)apfind.maxsep,,,>apfind.maxsep +order,s,h,)apfind.order,,,">apfind.order + +# RECENTERING PARAMETERS +" +aprecenter,s,h,)aprecenter.aprecenter,,,>aprecenter.aprecenter +npeaks,r,h,)aprecenter.npeaks,,,>aprecenter.npeaks +shift,b,h,)aprecenter.shift,,,">aprecenter.shift + +# RESIZING PARAMETERS +" +llimit,r,h,)apresize.llimit,,,>apresize.llimit +ulimit,r,h,)apresize.ulimit,,,>apresize.ulimit +ylevel,r,h,)apresize.ylevel,,,>apresize.ylevel +peak,b,h,)apresize.peak,,,>apresize.peak +bkg,b,h,)apresize.bkg,,,>apresize.bkg +r_grow,r,h,)apresize.r_grow,,,>apresize.r_grow +avglimits,b,h,)apresize.avglimits,,,">apresize.avglimits + +# EDITING PARAMETERS +" +e_output,s,q,,,,Output spectra rootname +e_profiles,s,q,,,,Profile reference image + +# TRACING PARAMETERS +t_nsum,i,h,)aptrace.nsum,,,>aptrace.nsum +t_step,i,h,)aptrace.step,,,>aptrace.step +t_nlost,i,h,)aptrace.nlost,,,>aptrace.nlost +t_width,r,h,)apedit.width,,,>apedit.width +t_function,s,h,)aptrace.function,,,>aptrace.function +t_order,i,h,)aptrace.order,,,>aptrace.order +t_sample,s,h,)aptrace.sample,,,>aptrace.sample +t_naverage,i,h,)aptrace.naverage,,,>aptrace.naverage +t_niterate,i,h,)aptrace.niterate,,,>aptrace.niterate +t_low_reject,r,h,)aptrace.low_reject,,,>aptrace.low_reject +t_high_reject,r,h,)aptrace.high_reject,,,>aptrace.high_reject +t_grow,r,h,)aptrace.grow,,,">aptrace.grow + +# EXTRACTION PARAMETERS +" +background,s,h,)apfit.background,,,>apfit.background +skybox,i,h,)apfit.skybox,,,>apfit.skybox +weights,s,h,"none",,,Extraction weights (none|variance) +pfit,s,h,)apfit.pfit,,,>apfit.pfit +clean,b,h,)apfit.clean,,,>apfit.clean +nclean,r,h,0.5,,,Maximum number of pixels to clean +niterate,i,h,5,0,,Number of profile fitting iterations +saturation,r,h,)apfit.saturation,,,>apfit.saturation +readnoise,s,h,)apfit.readnoise,,,>apfit.readnoise +gain,s,h,)apfit.gain,,,>apfit.gain +lsigma,r,h,)apfit.lsigma,,,>apfit.lsigma +usigma,r,h,)apfit.usigma,,,>apfit.usigma +polysep,r,h,0.90,0.1,0.95,Marsh algorithm polynomial spacing +polyorder,i,h,10,1,,Marsh algorithm polynomial order +nsubaps,i,h,1,,,"Number of subapertures per aperture + +# ANSWER PARAMETERS +" +ansclobber,s,h,"no",,," " +ansclobber1,s,h,"no",,," " +ansdbwrite,s,h,"yes",,," " +ansdbwrite1,s,h,"yes",,," " +ansedit,s,h,"yes",,," " +ansextract,s,h,"yes",,," " +ansfind,s,h,"yes",,," " +ansfit,s,h,"yes",,," " +ansfitscatter,s,h,"yes",,," " +ansfitsmooth,s,h,"yes",,," " +ansfitspec,s,h,"yes",,," " +ansfitspec1,s,h,"yes",,," " +ansfittrace,s,h,"yes",,," " +ansfittrace1,s,h,"yes",,," " +ansflat,s,h,"yes",,," " +ansmask,s,h,"yes",,," " +ansnorm,s,h,"yes",,," " +ansrecenter,s,h,"yes",,," " +ansresize,s,h,"yes",,," " +ansreview,s,h,"yes",,," " +ansreview1,s,h,"yes",,," " +ansscat,s,h,"yes",,," " +anssmooth,s,h,"yes",,," " +anstrace,s,h,"yes",,," " diff --git a/noao/twodspec/apextract/apflat1.par b/noao/twodspec/apextract/apflat1.par new file mode 100644 index 00000000..0fac8391 --- /dev/null +++ b/noao/twodspec/apextract/apflat1.par @@ -0,0 +1,117 @@ +# OUTPUT PARAMETERS + +format,s,h,)apsum.format,,,>apsum.format +extras,b,h,)apsum.extras,,,>apsum.extras +dbwrite,s,h,yes,,,Write to database? +initialize,b,h,yes,,,Initialize answers? +verbose,b,h,)_.verbose,,,"Verbose output? + +# DEFAULT APERTURE PARAMETERS +" +lower,r,h,)apdefault.lower,,,>apdefault.lower +upper,r,h,)apdefault.upper,,,>apdefault.upper +apidtable,s,h,)apdefault.apidtable,,,">apdefault.apidtable + +# DEFAULT BACKGROUND PARAMETERS +" +b_function,s,h,)apdefault.b_function,,,>apdefault.b_function +b_order,i,h,)apdefault.b_order,,,>apdefault.b_order +b_sample,s,h,)apdefault.b_sample,,,>apdefault.b_sample +b_naverage,i,h,)apdefault.b_naverage,,,>apdefault.b_naverage +b_niterate,i,h,)apdefault.b_niterate,,,>apdefault.b_niterate +b_low_reject,r,h,)apdefault.b_low_reject,,,>apdefault.b_low_reject +b_high_reject,r,h,)apdefault.b_high_reject,,,>apdefault.b_high_reject +b_grow,r,h,)apdefault.b_grow,,,">apdefault.b_grow + +# APERTURE CENTERING PARAMETERS +" +width,r,h,)apedit.width,,,>apedit.width +radius,r,h,)apedit.radius,,,>apedit.radius +threshold,r,h,)apedit.threshold,,,">apedit.threshold + +# AUTOMATIC FINDING AND ORDERING PARAMETERS +" +nfind,i,h,)apfind.nfind,,,>apfind.nfind +minsep,r,h,)apfind.minsep,,,>apfind.minsep +maxsep,r,h,)apfind.maxsep,,,>apfind.maxsep +order,s,h,)apfind.order,,,">apfind.order + +# RECENTERING PARAMETERS +" +aprecenter,s,h,)aprecenter.aprecenter,,,>aprecenter.aprecenter +npeaks,r,h,)aprecenter.npeaks,,,>aprecenter.npeaks +shift,b,h,)aprecenter.shift,,,">aprecenter.shift + +# RESIZING PARAMETERS +" +llimit,r,h,)apresize.llimit,,,>apresize.llimit +ulimit,r,h,)apresize.ulimit,,,>apresize.ulimit +ylevel,r,h,)apresize.ylevel,,,>apresize.ylevel +peak,b,h,)apresize.peak,,,>apresize.peak +bkg,b,h,)apresize.bkg,,,>apresize.bkg +r_grow,r,h,)apresize.r_grow,,,>apresize.r_grow +avglimits,b,h,)apresize.avglimits,,,">apresize.avglimits + +# EDITING PARAMETERS +" +e_output,s,q,,,,Output spectra rootname +e_profiles,s,q,,,,Profile reference image + +# TRACING PARAMETERS +t_nsum,i,h,)aptrace.nsum,,,>aptrace.nsum +t_step,i,h,)aptrace.step,,,>aptrace.step +t_nlost,i,h,)aptrace.nlost,,,>aptrace.nlost +t_width,r,h,)apedit.width,,,>apedit.width +t_function,s,h,)aptrace.function,,,>aptrace.function +t_order,i,h,)aptrace.order,,,>aptrace.order +t_sample,s,h,)aptrace.sample,,,>aptrace.sample +t_naverage,i,h,)aptrace.naverage,,,>aptrace.naverage +t_niterate,i,h,)aptrace.niterate,,,>aptrace.niterate +t_low_reject,r,h,)aptrace.low_reject,,,>aptrace.low_reject +t_high_reject,r,h,)aptrace.high_reject,,,>aptrace.high_reject +t_grow,r,h,)aptrace.grow,,,">aptrace.grow + +# EXTRACTION PARAMETERS +" +background,s,h,"none",,,>apflatten.background +skybox,i,h,1,,,>apflatten.skybox +weights,s,h,"none",,,Extraction weights (none|variance) +pfit,s,h,)apflatten.pfit,,,>apflatten.pfit +clean,b,h,)apflatten.clean,,,>apflatten.clean +nclean,r,h,0.5,,,Maximum number of pixels to clean +niterate,i,h,5,0,,Number of profile fitting iterations +saturation,r,h,)apflatten.saturation,,,>apflatten.saturation +readnoise,s,h,)apflatten.readnoise,,,>apflatten.readnoise +gain,s,h,)apflatten.gain,,,>apflatten.gain +lsigma,r,h,)apflatten.lsigma,,,>apflatten.lsigma +usigma,r,h,)apflatten.usigma,,,>apflatten.usigma +polysep,r,h,0.90,0.1,0.90,Marsh algorithm polynomial spacing +polyorder,i,h,10,1,,Marsh algorithm polynomial order +nsubaps,i,h,1,,,"Number of subapertures per aperture + +# ANSWER PARAMETERS +" +ansclobber,s,h,"no",,," " +ansclobber1,s,h,"no",,," " +ansdbwrite,s,h,"yes",,," " +ansdbwrite1,s,h,"yes",,," " +ansedit,s,h,"yes",,," " +ansextract,s,h,"yes",,," " +ansfind,s,h,"yes",,," " +ansfit,s,h,"yes",,," " +ansfitscatter,s,h,"yes",,," " +ansfitsmooth,s,h,"yes",,," " +ansfitspec,s,h,"yes",,," " +ansfitspec1,s,h,"yes",,," " +ansfittrace,s,h,"yes",,," " +ansfittrace1,s,h,"yes",,," " +ansflat,s,h,"yes",,," " +ansmask,s,h,"yes",,," " +ansnorm,s,h,"yes",,," " +ansrecenter,s,h,"yes",,," " +ansresize,s,h,"yes",,," " +ansreview,s,h,"yes",,," " +ansreview1,s,h,"yes",,," " +ansscat,s,h,"yes",,," " +anssmooth,s,h,"yes",,," " +anstrace,s,h,"yes",,," " diff --git a/noao/twodspec/apextract/apflatten.par b/noao/twodspec/apextract/apflatten.par new file mode 100644 index 00000000..84e5906c --- /dev/null +++ b/noao/twodspec/apextract/apflatten.par @@ -0,0 +1,37 @@ +# APFLATTEN + +input,s,a,,,,List of images to flatten +output,s,a,,,,List of output flatten images +apertures,s,h,"",,,Apertures +references,s,h,"",,,"List of reference images +" +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,yes,,,Recenter apertures? +resize,b,h,yes,,,Resize apertures? +edit,b,h,yes,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,Fit traced points interactively? +flatten,b,h,yes,,,Flatten spectra? +fitspec,b,h,yes,,,"Fit normalization spectra interactively? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,10,,,Number of dispersion lines to sum or median +threshold,r,h,10.,,,"Threshold for flattening spectra +" +pfit,s,h,"fit1d","fit1d|fit2d",,Profile fitting type (fit1d|fit2d) +clean,b,h,no,,,Detect and replace bad pixels? +saturation,r,h,INDEF,,,Saturation level +readnoise,s,h,"0.",,,Read out noise sigma (photons) +gain,s,h,"1.",,,Photon gain (photons/data number) +lsigma,r,h,4.,0.,,Lower rejection threshold +usigma,r,h,4.,0.,,"Upper rejection threshold +" +function,s,h,"legendre","chebyshev|legendre|spline1|spline3",,Fitting function for normalization spectra +order,i,h,1,1,,Fitting function order +sample,s,h,"*",,,Sample regions +naverage,i,h,1,,,Average or median +niterate,i,h,0,0,,Number of rejection iterations +low_reject,r,h,3.,0.,,Lower rejection sigma +high_reject,r,h,3.,0.,,High upper rejection sigma +grow,r,h,0.,0.,,Rejection growing radius diff --git a/noao/twodspec/apextract/apgetdata.x b/noao/twodspec/apextract/apgetdata.x new file mode 100644 index 00000000..6645a6c3 --- /dev/null +++ b/noao/twodspec/apextract/apgetdata.x @@ -0,0 +1,99 @@ +include <imhdr.h> + +# AP_GETDATA -- Get the summed dispersion line. +# Return the IMIO pointer, pointer to image data, the aperture axis and title. +# The pointers must be freed by the calling program. Note that the value of +# line may be changed. + +procedure ap_getdata (image, line, nsum, im, imdata, npts, apaxis, title) + +char image[SZ_FNAME] # Image name +int line # Dispersion line to graph +int nsum # Number of dispersion lines to sum +pointer im # IMIO pointer +pointer imdata # Pointer to image data +int npts # Number of pixels +int apaxis # Aperture axis +pointer title # Title for image data + +int i, j, k, l, n, dispaxis +pointer buf, medbuf + +real asumr(), amedr() +pointer ap_immap(), imgs2r() + +errchk ap_immap, imgs2r + +begin + # Map the image + im = ap_immap (image, apaxis, dispaxis) + + # Determine the dispersion and aperture axes. + if (IS_INDEFI (line)) + line = IM_LEN(im, dispaxis) / 2 + else + line = max (1, min (IM_LEN(im, dispaxis), line)) + + # Allocate memory for the image line and title. + npts = IM_LEN(im, apaxis) + call calloc (imdata, npts, TY_REAL) + call malloc (title, SZ_LINE, TY_CHAR) + + # Sum the specified number of dispersion lines. + n = max (1, abs (nsum)) + switch (apaxis) { + case 1: + i = max (1, line - n / 2) + j = min (IM_LEN(im, dispaxis), i + n - 1) + i = max (1, j - n + 1) + buf = imgs2r (im, 1, npts, i, j) + j = j - i + 1 + if (j < 3 || nsum > 0) { + do k = 1, j + call aaddr (Memr[buf+(k-1)*npts], Memr[imdata], + Memr[imdata], npts) + call sprintf (Memc[title], SZ_LINE, + "Image=%s, Sum of lines %d-%d") + call pargstr (image) + call pargi (i) + call pargi (i+j-1) + } else { + call malloc (medbuf, j, TY_REAL) + do k = 0, npts-1 { + do l = 0, j-1 + Memr[medbuf+l] = Memr[buf+l*npts+k] + Memr[imdata+k] = amedr (Memr[medbuf], j) + } + call mfree (medbuf, TY_REAL) + call sprintf (Memc[title], SZ_LINE, + "Image=%s, Median of lines %d-%d") + call pargstr (image) + call pargi (i) + call pargi (i+j-1) + } + + case 2: + i = max (1, line - n / 2) + j = min (IM_LEN(im, dispaxis), i + n - 1) + i = max (1, j - n + 1) + buf = imgs2r (im, i, j, 1, npts) + j = j - i + 1 + if (j < 3 || nsum > 0) { + do k = 1, npts + Memr[imdata+k-1] = asumr (Memr[buf+(k-1)*j], j) + call sprintf (Memc[title], SZ_LINE, + "Image=%s, Sum of columns %d-%d") + call pargstr (image) + call pargi (i) + call pargi (i+j-1) + } else { + do k = 1, npts + Memr[imdata+k-1] = amedr (Memr[buf+(k-1)*j], j) + call sprintf (Memc[title], SZ_LINE, + "Image=%s, Median of columns %d-%d") + call pargstr (image) + call pargi (i) + call pargi (i+j-1) + } + } +end diff --git a/noao/twodspec/apextract/apgetim.x b/noao/twodspec/apextract/apgetim.x new file mode 100644 index 00000000..c5bc96f8 --- /dev/null +++ b/noao/twodspec/apextract/apgetim.x @@ -0,0 +1,73 @@ +# AP_GETIM -- Standardize image name so that different ways of specifying +# the images map to the same database and output rootnames. + +int procedure ap_getim (list, image, maxchar) + +int list #I Image list +char image[maxchar] #O Image name +int maxchar #I Maximum number of chars in image name + +char ksection[SZ_FNAME] #O Image name + +int i, j, stat, cl_index, cl_size +pointer im +pointer sp, cluster, section + +int imtgetim(), strlen(), stridxs(), ctoi() +pointer immap() + +begin + # Get next image name. + stat = imtgetim (list, image, maxchar) + if (stat == EOF) + return (stat) + + call smark (sp) + call salloc (cluster, SZ_FNAME, TY_CHAR) + call salloc (section, SZ_FNAME, TY_CHAR) + + call imparse (image, Memc[cluster], SZ_FNAME, ksection, SZ_FNAME, + Memc[section], SZ_FNAME, cl_index, cl_size) + + # Strip the extension. + call xt_imroot (Memc[cluster], Memc[cluster], SZ_FNAME) + + # Generate standard ksection. Only map image if index used. + # Don't worry about cases with both an index and ksection. + + if (cl_index < 0 && ksection[1] == EOS) + ; + else if (cl_index == 0) + ksection[1] = EOS + else { + if (cl_index > 0) { + im = immap (image, READ_ONLY, 0) + ksection[1] = '[' + call imgstr (im, "extname", ksection[2], SZ_FNAME-1) + i = strlen (ksection) + ifnoerr (call imgstr (im, "extver" , + ksection[i+2], SZ_FNAME-i-1)) { + ksection[i+1] = ',' + i = strlen (ksection) + } + ksection[i+1] = ']' + ksection[i+2] = EOS + call imunmap (im) + } else { + i = stridxs (",", ksection[2]) + 2 + if (i > 2) { + j = ctoi (ksection, i, j) + ksection[i] = ']' + ksection[i+1] = EOS + } + } + } + + call sprintf (image, maxchar, "%s%s%s") + call pargstr (Memc[cluster]) + call pargstr (ksection) + call pargstr (Memc[section]) + + call sfree (sp) + return (stat) +end diff --git a/noao/twodspec/apextract/apgmark.x b/noao/twodspec/apextract/apgmark.x new file mode 100644 index 00000000..72ad6a68 --- /dev/null +++ b/noao/twodspec/apextract/apgmark.x @@ -0,0 +1,126 @@ +include <pkg/rg.h> +include "apertures.h" + +# AP_GMARK -- Mark an aperture. + +define SZ_TEXT 10 # Maximum size of aperture number string + +procedure ap_gmark (gp, imvec, aps, naps) + +pointer gp # GIO pointer +int imvec # Image vector +pointer aps[ARB] # Aperture data +int naps # Number of apertures + +int i, apaxis +real x1, x2, y1, y2, dy, xc, xl, xu +pointer sp, text, format, ap + +int itoc() +real ap_cveval() + +begin + # The aperture is marked at the top of the graph. + call smark (sp) + call salloc (text, SZ_TEXT, TY_CHAR) + + call ggwind (gp, xl, xu, y1, y2) + x1 = min (xl, xu) + x2 = max (xl, xu) + dy = 0.025 * (y2 - y1) + y1 = y2 - 4 * dy + + if (naps > 20) { + call salloc (format, SZ_LINE, TY_CHAR) + call sprintf (Memc[format], SZ_LINE, "h=c,v=b,s=%4.2f") + call pargr (20. / naps) + } + + for (i = 1; i <= naps; i = i + 1) { + ap = aps[i] + apaxis = AP_AXIS(ap) + + xc = AP_CEN(ap, apaxis) + ap_cveval (AP_CV(ap), real (imvec)) + xl = xc + AP_LOW(ap, apaxis) + xu = xc + AP_HIGH(ap, apaxis) + call gline (gp, xc, y1 - 2 * dy, xc, y1 + 2 * dy) + call gline (gp, xl, y1 - dy, xl, y1 + dy) + call gline (gp, xu, y1 - dy, xu, y1 + dy) + call gline (gp, xl, y1, xu, y1) + if ((xc > x1) && (xc < x2)) { + if (itoc (AP_ID(ap), Memc[text], SZ_TEXT) > 0) { + if (naps > 20) + call gtext (gp, xc, y1 + 2.5 * dy, Memc[text], + Memc[format]) + else + call gtext (gp, xc, y1 + 2.5 * dy, Memc[text], + "h=c,v=b") + } + } + } + + call sfree (sp) +end + + +# AP_GMARKB -- Mark backgrounds. + +procedure ap_gmarkb (gp, imvec, aps, naps) + +pointer gp # GIO pointer +int imvec # Image vector +pointer aps[ARB] # Aperture data +int naps # Number of apertures + +int i, j, nx, apaxis +real x1, x2, y1, y2, dy, xc, xl, xu +pointer sp, sample, x, ap, rg + +real ap_cveval() +pointer rg_xrangesr() + +begin + call smark (sp) + call salloc (sample, SZ_LINE, TY_CHAR) + + # The background is marked at the bottom of the graph. + call ggwind (gp, xl, xu, y1, y2) + x1 = min (xl, xu) + x2 = max (xl, xu) + dy = 0.005 * (y2 - y1) + y1 = y1 + 4 * dy + + # Allocate x array. + nx = x2 - x1 + 2 + call salloc (x, nx, TY_REAL) + + for (i = 1; i <= naps; i = i + 1) { + ap = aps[i] + apaxis = AP_AXIS(ap) + + xc = AP_CEN(ap, apaxis) + ap_cveval (AP_CV(ap), real (imvec)) + + if (AP_IC(ap) == NULL) + next + call ic_gstr (AP_IC(ap), "sample", Memc[sample], SZ_LINE) + + do j = 0, nx-1 + Memr[x+j] = x1 + j - xc + rg = rg_xrangesr (Memc[sample], Memr[x], nx) + + do j = 1, RG_NRGS(rg) { + xl = Memr[x+RG_X1(rg,j)-1] + xc + xu = Memr[x+RG_X2(rg,j)-1] + xc + if (xl > x1 && xl < x2) + call gline (gp, xl, y1-dy, xl, y1+dy) + if (xu > x1 && xu < x2) + call gline (gp, xu, y1-dy, xu, y1+dy) + call gline (gp, xl, y1, xu, y1) + + } + + call rg_free (rg) + } + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apgraph.x b/noao/twodspec/apextract/apgraph.x new file mode 100644 index 00000000..47d71646 --- /dev/null +++ b/noao/twodspec/apextract/apgraph.x @@ -0,0 +1,145 @@ +include <pkg/gtools.h> +include "apertures.h" + + +# AP_GRAPH -- Graph the image data and call ap_gmark to mark the apertures. + +procedure ap_graph (gp, gt, imdata, npts, imvec, aps, naps) + +pointer gp # GIO pointer +pointer gt # GTOOLS pointer +real imdata[npts] # Image data +int npts # Number points in image data +int imvec # Image vector +pointer aps[ARB] # Aperture pointers +int naps # Number of apertures + +real x1, x2 + +begin + call gclear (gp) + + x1 = 1. + x2 = npts + call gswind (gp, x1, x2, INDEF, INDEF) + call gascale (gp, imdata, npts, 2) + call gt_swind (gp, gt) + call gt_labax (gp, gt) + call gvline (gp, imdata, npts, x1, x2) + + call ap_gmark (gp, imvec, aps, naps) + if (naps == 1) + call ap_gmarkb (gp, imvec, aps, naps) +end + + +# AP_PLOT -- Make a plot of the apertures if plot output is defined. + +procedure ap_plot (image, line, nsum, aps, naps) + +char image[SZ_FNAME] # Image to be edited +int line # Dispersion line +int nsum # Number of dispersion lines to sum + +pointer aps[ARB] # Aperture pointers +int naps # Number of apertures + +int npts, apaxis, fd +pointer im, imdata, title, gp, gt, gt_init() +errchk ap_getdata, ap_popen + +begin + call ap_popen (gp, fd, "aps") + if (gp == NULL) + return + + # Map the image and get the image data. + call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, title) + + gt = gt_init() + call gt_sets (gt, GTTITLE, Memc[title]) + call gt_sets (gt, GTPARAMS, "") + call gt_setr (gt, GTXMIN, INDEF) + call gt_setr (gt, GTXMAX, INDEF) + call gt_setr (gt, GTYMIN, INDEF) + call gt_setr (gt, GTYMAX, INDEF) + + call ap_graph (gp, gt, Memr[imdata], npts, line, aps, naps) + + call mfree (imdata, TY_REAL) + call mfree (title, TY_CHAR) + call ap_pclose (gp, fd) + call gt_free (gt) + call imunmap (im) +end + + +# AP_GRAPH1 -- Make a graph of the extracted 1D spectrum. + +procedure ap_graph1 (gt, bufout, npts, nspec) + +pointer gt # GTOOLS pointer +real bufout[npts, nspec] # Data +int npts # Number of data points +int nspec # Number of spectra + +real wx, wy +int i, wcs, key, gt_gcur() +pointer sp, str, gp +errchk ap_gopen + +begin + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + + call ap_gopen (gp) + call gclear (gp) + call gswind (gp, 1., real (npts), INDEF, INDEF) + call gascale (gp, bufout, npts * nspec, 2) + call gt_swind (gp, gt) + call gt_labax (gp, gt) + do i = 1, nspec + call gvline (gp, bufout[1,i], npts, 1., real (npts)) + call gflush (gp) + + while (gt_gcur ("gcur", wx, wy, wcs, key, Memc[str], + SZ_LINE) != EOF) { + switch (key) { + case 'I': + call fatal (0, "Interrupt") + } + } + + call sfree (sp) +end + + +# AP_PLOT1 -- Make a plot of the extracted 1D spectrum. + +procedure ap_plot1 (gt, bufout, npts, nspec) + +pointer gt # GTOOLS pointer +real bufout[npts,nspec] # Data +int npts # Number of data points +int nspec # Number of spectra + +int i, fd +pointer gp +errchk ap_popen + +begin + call ap_popen (gp, fd, "spec") + if (gp == NULL) + return + + call gclear (gp) + call gswind (gp, 1., real (npts), INDEF, INDEF) + call gascale (gp, bufout, npts * nspec, 2) + call gt_swind (gp, gt) + call gt_labax (gp, gt) + do i = 1, nspec + call gvline (gp, bufout[1,i], npts, 1., real (npts)) + call gflush (gp) + + call ap_pclose (gp, fd) +end diff --git a/noao/twodspec/apextract/apgscur.x b/noao/twodspec/apextract/apgscur.x new file mode 100644 index 00000000..5306ff9a --- /dev/null +++ b/noao/twodspec/apextract/apgscur.x @@ -0,0 +1,28 @@ +include "apertures.h" + +# AP_GSCUR -- Set the graphics cursor to the aperture given by the index. +# It computes the position of the cursor for the specified dispersion line. + +procedure ap_gscur (index, gp, line, aps, y) + +int index # Index of aperture +pointer gp # GIO pointer +int line # Dispersion line +pointer aps[ARB] # Apertures +real y # Y cursor coordinate + +int apaxis +real x +pointer ap + +real ap_cveval() + +begin + if (index < 1 || IS_INDEF (y)) + return + + ap = aps[index] + apaxis = AP_AXIS(ap) + x = AP_CEN(ap, apaxis) + ap_cveval (AP_CV(ap), real (line)) + call gscur (gp, x, y) +end diff --git a/noao/twodspec/apextract/apicset.x b/noao/twodspec/apextract/apicset.x new file mode 100644 index 00000000..b837a991 --- /dev/null +++ b/noao/twodspec/apextract/apicset.x @@ -0,0 +1,84 @@ +include <imhdr.h> +include "apertures.h" + +# AP_ICSET -- Set the background fitting ICFIT structure for an aperture. +# If the input template aperture is NULL then the output background fitting +# ICFIT pointer is initialized otherwise a copy from the input template +# aperture is made. + +procedure ap_icset (apin, apout, imlen) + +pointer apin # Input template aperture pointer +pointer apout # Output aperture pointer +int imlen # Image length along aperture axis + +int i +real x, x1, x2 +pointer ic, sp, str + +int apgeti(), ctor() +real apgetr() + +begin + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + + if (AP_IC(apout) == NULL) + call ic_open (AP_IC(apout)) + ic = AP_IC(apout) + + if (apin == NULL) { + call apgstr ("b_function", Memc[str], SZ_LINE) + call ic_pstr (ic, "function", Memc[str]) + call ic_puti (ic, "order", apgeti ("b_order")) + call apgstr ("b_sample", Memc[str], SZ_LINE) + for (i=str; Memc[i]==' '; i=i+1) + ; + if (Memc[i] == EOS) + call strcpy ("*", Memc[str], SZ_LINE) + call ic_pstr (ic, "sample", Memc[str]) + call ic_puti (ic, "naverage", apgeti ("b_naverage")) + call ic_puti (ic, "niterate", apgeti ("b_niterate")) + call ic_putr (ic, "low", apgetr ("b_low_reject")) + call ic_putr (ic, "high", apgetr ("b_high_reject")) + call ic_putr (ic, "grow", apgetr ("b_grow")) + if (AP_AXIS(apout) == 1) + call ic_pstr (ic, "xlabel", "Column") + else + call ic_pstr (ic, "xlabel", "Line") + } else { + if (AP_IC(apin) == NULL) { + call ic_closer (AP_IC(apout)) + AP_IC(apout) = NULL + ic = NULL + } else if (AP_IC(apin) != ic) + call ic_copy (AP_IC(apin), ic) + } + + # Set the background limits + if (ic != NULL) { + i = AP_AXIS(apout) + x1 = AP_LOW(apout, i) + x2 = AP_HIGH(apout, i) + + call ic_gstr (ic, "sample", Memc[str], SZ_LINE) + for (i=str; Memc[i]!=EOS; i=i+1) + if (Memc[i] == ':') + Memc[i] = ',' + for (i=1; Memc[str+i-1]!=EOS; i=i+1) { + if (Memc[str+i-1] == '*') { + x1 = min (x1, real(-imlen)) + x2 = max (x2, real(imlen)) + } else if (ctor (Memc[str], i, x) > 0) { + x1 = min (x1, x) + x2 = max (x2, x) + i = i - 1 + } + } + + call ic_putr (ic, "xmin", x1) + call ic_putr (ic, "xmax", x2) + } + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apids.x b/noao/twodspec/apextract/apids.x new file mode 100644 index 00000000..572890a5 --- /dev/null +++ b/noao/twodspec/apextract/apids.x @@ -0,0 +1,401 @@ +include <error.h> +include <mach.h> +include "apertures.h" + +# Data structure for user aperture id table. +define IDS_LEN 4 # Length of ID structure +define IDS_NIDS Memi[$1] # Number of aperture IDs +define IDS_APS Memi[$1+1] # Aperture numbers (pointer) +define IDS_BEAMS Memi[$1+2] # Beam numbers (pointer) +define IDS_TITLES Memi[$1+3] # Titles (pointer) + +# AP_GIDS -- Get user aperture ID's. + +procedure ap_gids (ids) + +pointer ids # ID structure + +int nids, ap, beam, fd, nalloc +double ra, dec +pointer sp, key, str, aps, beams, titles, im, list + +int nowhite(), open(), fscan(), nscan() +pointer immap(), imofnlu(), imgnfn() +errchk open + +begin + call smark (sp) + call salloc (key, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + + nids = 0 + nalloc = 0 + + call apgstr ("apidtable", Memc[key], SZ_FNAME) + if (nowhite (Memc[key], Memc[key], SZ_FNAME) > 0) { + iferr { + # Read aperture information from an image. + ifnoerr (im = immap (Memc[key], READ_ONLY, 0)) { + list = imofnlu (im, "SLFIB[0-9]*") + while (imgnfn (list, Memc[key], SZ_FNAME) != EOF) { + call imgstr (im, Memc[key], Memc[str], SZ_LINE) + call sscan (Memc[str]) + call gargi (ap) + if (nscan() == 0) + next + if (ap < 1) { + call imcfnl (list) + call imunmap (im) + call error (1, + "Aperture numbers in apidtable must be > 0") + } + if (nalloc == 0) { + nalloc = 50 + call malloc (aps, nalloc, TY_INT) + call malloc (beams, nalloc, TY_INT) + call malloc (titles, nalloc, TY_POINTER) + } else if (nids == nalloc) { + nalloc = nalloc + 50 + call realloc (aps, nalloc, TY_INT) + call realloc (beams, nalloc, TY_INT) + call realloc (titles, nalloc, TY_POINTER) + } + Memi[aps+nids] = ap + call gargi (Memi[beams+nids]) + call gargd (ra) + call gargd (dec) + if (nscan() != 4) { + call reset_scan () + call gargi (ap) + call gargi (beam) + Memc[str] = EOS + call gargstr (Memc[str], SZ_LINE) + call xt_stripwhite (Memc[str]) + if (Memc[str] == EOS) + Memi[titles+nids] = NULL + else { + call malloc (Memi[titles+nids], SZ_APTITLE, + TY_CHAR) + call strcpy (Memc[str], Memc[Memi[titles+nids]], + SZ_APTITLE) + } + } else { + Memc[str] = EOS + call gargstr (Memc[str], SZ_LINE) + call xt_stripwhite (Memc[str]) + call malloc (Memi[titles+nids], SZ_APTITLE, TY_CHAR) + if (Memc[str] == EOS) { + call sprintf (Memc[Memi[titles+nids]], + SZ_APTITLE, "(%.2h %.2h)") + call pargd (ra) + call pargd (dec) + } else { + call sprintf (Memc[Memi[titles+nids]], + SZ_APTITLE, "%s (%.2h %.2h)") + call pargstr (Memc[str]) + call pargd (ra) + call pargd (dec) + } + } + nids = nids + 1 + } + call imcfnl (list) + call imunmap (im) + + # Read aperture information from a file. + } else { + fd = open (Memc[key], READ_ONLY, TEXT_FILE) + while (fscan (fd) != EOF) { + call gargi (ap) + if (nscan() == 0) + next + if (ap < 1) { + call close (fd) + call error (1, + "Aperture numbers in apidtable must be > 0") + } + if (nalloc == 0) { + nalloc = 50 + call malloc (aps, nalloc, TY_INT) + call malloc (beams, nalloc, TY_INT) + call malloc (titles, nalloc, TY_POINTER) + } else if (nids == nalloc) { + nalloc = nalloc + 50 + call realloc (aps, nalloc, TY_INT) + call realloc (beams, nalloc, TY_INT) + call realloc (titles, nalloc, TY_POINTER) + } + Memi[aps+nids] = ap + Memi[beams+nids] = ap + Memc[str] = EOS + call gargi (beam) + if (nscan() == 2) + Memi[beams+nids] = beam + call gargstr (Memc[str], SZ_LINE) + call xt_stripwhite (Memc[str]) + if (Memc[str] == EOS) + Memi[titles+nids] = NULL + else { + call malloc (Memi[titles+nids], SZ_APTITLE, TY_CHAR) + call strcpy (Memc[str], Memc[Memi[titles+nids]], + SZ_APTITLE) + } + nids = nids + 1 + } + call close (fd) + } + } then + call erract (EA_WARN) + } + + if (nalloc > nids) { + call realloc (aps, nids, TY_INT) + call realloc (beams, nids, TY_INT) + call realloc (titles, nids, TY_INT) + } + + if (nids > 0) { + call malloc (ids, IDS_LEN, TY_STRUCT) + IDS_NIDS(ids) = nids + IDS_APS(ids) = aps + IDS_BEAMS(ids) = beams + IDS_TITLES(ids) = titles + } + + call sfree (sp) +end + + +procedure ap_fids (ids) + +pointer ids # ID structure +int i + +begin + if (ids != NULL) { + do i = 1, IDS_NIDS(ids) + call mfree (Memi[IDS_TITLES(ids)+i-1], TY_CHAR) + call mfree (IDS_APS(ids), TY_INT) + call mfree (IDS_BEAMS(ids), TY_INT) + call mfree (IDS_TITLES(ids), TY_POINTER) + call mfree (ids, TY_STRUCT) + } +end + + + +# AP_IDS -- Set aperture IDs +# Do not allow negative or zero aperture numbers. + +procedure ap_ids (aps, naps, ids) + +pointer aps[ARB] # Aperture pointers +int naps # Number of apertures +int ids # ID structure + +int i, j, k, l, m, axis, nids, ap, beam, skip, nused +real maxsep, apgetr() +pointer sp, used, a, b + +begin + if (naps < 1) + return + + axis = AP_AXIS(aps[1]) + maxsep = apgetr ("maxsep") + + # Dereference ID structure pointers. + if (ids != NULL) { + nids = IDS_NIDS(ids) + a = IDS_APS(ids) + b = IDS_BEAMS(ids) + } else + nids = 0 + + # Make a list of used aperture numbers + call smark (sp) + call salloc (used, naps, TY_INT) + nused = 0 + do i = 1, naps + if (!IS_INDEFI(AP_ID(aps[i]))) { + Memi[used+nused] = AP_ID(aps[i]) + nused = nused + 1 + } + + # Find first aperture with a defined aperture number. + for (i=1; i<=naps && IS_INDEFI(AP_ID(aps[i])); i=i+1) + ; + + # If there are no defined aperture numbers start with 1 or first + # aperture in the ID table. + + if (i > naps) { + i = 1 + if (nids > 0) { + ap = Memi[a] + beam = Memi[b] + } else { + ap = i + beam = ap + } + AP_ID(aps[i]) = ap + AP_BEAM(aps[i]) = beam + Memi[used+nused] = ap + nused = nused + 1 + } else { + ap = AP_ID(aps[i]) + for (l = 1; l <= nids && ap != Memi[a+l-1]; l = l + 1) + ; + if (l <= nids) + AP_BEAM(aps[i]) = Memi[b+l-1] + else + AP_BEAM(aps[i]) = ap + } + + # Work backwards through the undefined apertures. + for (j = i - 1; j > 0; j = j - 1) { + skip = abs (AP_CEN(aps[j],axis)-AP_CEN(aps[j+1],axis)) / maxsep + if (ids != NULL) { + ap = AP_ID(aps[j+1]) + for (l = 1; l <= nids && ap != Memi[a+l-1]; l = l + 1) + ; + if (nids <= naps) + skip = 0 + m = l - skip + if (l > nids) { + l = 1 + for (k = 2; k <= nids; k = k + 1) + if (abs (ap - Memi[a+k-1]) < abs (ap - Memi[a+l-1])) + l = k + m = l - skip + 1 + } + repeat { + m = m - 1 + if (m > 0) { + ap = Memi[a+m-1] + beam = Memi[b+m-1] + } else { + ap = Memi[a+l-1] + m + beam = max (0, Memi[b+l-1] + m) + } + if (ap == 0) + next + for (k = 0; k < nused && abs(ap) != Memi[used+k]; k = k + 1) + ; + if (k == nused) + break + } + } else { + ap = AP_ID(aps[j+1]) - skip + repeat { + ap = ap - 1 + beam = abs (ap) + if (ap == 0) + next + for (k = 0; k < nused && abs(ap) != Memi[used+k]; k = k + 1) + ; + if (k == nused) + break + } + } + ap = abs (ap) + AP_ID(aps[j]) = ap + AP_BEAM(aps[j]) = beam + Memi[used+nused] = ap + nused = nused + 1 + } + + # Work forwards through the undefined apertures. + for (i = i + 1; i <= naps; i = i + 1) { + if (IS_INDEFI(AP_ID(aps[i]))) { + skip = abs (AP_CEN(aps[i],axis)-AP_CEN(aps[i-1],axis)) / maxsep + if (nids > 0) { + ap = AP_ID(aps[i-1]) + for (l = 1; l <= nids && ap != Memi[a+l-1]; l = l + 1) + ; + if (nids <= naps) + skip = 0 + m = l + skip + if (l > nids) { + l = 1 + for (k = 2; k <= nids; k = k + 1) + if (abs (ap-Memi[a+k-1]) < abs (ap-Memi[a+l-1])) + l = k + m = l + skip - 1 + } + m = nids - m + 1 + repeat { + m = m - 1 + if (m > 0) { + ap = Memi[a+nids-m] + beam = Memi[b+nids-m] + } else { + ap = Memi[a+l-1] - m + beam = max (0, Memi[b+l-1] - m) + } + if (ap == 0) + next + for (k=0; k<nused && abs(ap)!=Memi[used+k]; k=k+1) + ; + if (k == nused) + break + } + } else { + ap = AP_ID(aps[i-1]) + skip + repeat { + ap = ap + 1 + beam = abs (ap) + if (ap == 0) + next + for (k=0; k<nused && abs(ap)!=Memi[used+k]; k=k+1) + ; + if (k == nused) + break + } + } + ap = abs(ap) + AP_ID(aps[i]) = ap + AP_BEAM(aps[i]) = beam + Memi[used+nused] = ap + nused = nused + 1 + } + } + + call sfree (sp) +end + + +procedure ap_titles (aps, naps, ids) + +pointer aps[ARB] # Aperture pointers +int naps # Number of apertures +pointer ids # ID structure + +int i, j, nids +pointer a, titles, title + +begin + if (ids == NULL) + return + + nids = IDS_NIDS(ids) + a = IDS_APS(ids) + titles = IDS_TITLES(ids) + + do i = 1, naps { + if (AP_TITLE(aps[i]) != NULL) + next + do j = 1, nids { + if (AP_ID(aps[i]) == Memi[a+j-1]) { + title = Memi[titles+j-1] + if (title != NULL) { + if (AP_TITLE(aps[i]) == NULL) + call malloc (AP_TITLE(aps[i]), SZ_APTITLE, TY_CHAR) + call strcpy (Memc[title], Memc[AP_TITLE(aps[i])], + SZ_APTITLE) + } else if (AP_TITLE(aps[i]) != NULL) + call mfree (AP_TITLE(aps[i]), TY_CHAR) + } + } + } +end diff --git a/noao/twodspec/apextract/apimmap.x b/noao/twodspec/apextract/apimmap.x new file mode 100644 index 00000000..f001dc39 --- /dev/null +++ b/noao/twodspec/apextract/apimmap.x @@ -0,0 +1,48 @@ +include <imhdr.h> + +# AP_IMMAP -- Map an input image for the APEXTRACT package. + +pointer procedure ap_immap (image, apaxis, dispaxis) + +char image[ARB] # Image to map +int apaxis # Aperture axis +int dispaxis # Dispersion axis + +pointer im, immap() +int i, j, imgeti(), clgeti() +errchk immap + +data i/0/, j/0/ + +begin + im = immap (image, READ_ONLY, 0) + if (IM_NDIM(im) == 1) { + call imunmap (im) + call error (0, "Image must be two dimensional") + } else if (IM_NDIM(im) > 2) { + if (i == 0) + call eprintf ( + "Warning: Image(s) are not two dimensional (ignoring higher dimensions)\n") + i = i + 1 + } else + i = 0 + + iferr (dispaxis = imgeti (im, "dispaxis")) + dispaxis = clgeti ("dispaxis") + if (dispaxis < 1 || dispaxis > 2) { + apaxis = dispaxis + dispaxis = max (1, min (2, clgeti ("dispaxis"))) + if (j == 0) { + call eprintf ( + "WARNING: Dispersion axis %d invalid; using axis %d\n") + call pargi (apaxis) + call pargi (dispaxis) + } + j = j + 1 + } else + j = 0 + + apaxis = mod (dispaxis, 2) + 1 + + return (im) +end diff --git a/noao/twodspec/apextract/apinfo.x b/noao/twodspec/apextract/apinfo.x new file mode 100644 index 00000000..372860ae --- /dev/null +++ b/noao/twodspec/apextract/apinfo.x @@ -0,0 +1,96 @@ +include "apertures.h" + +# AP_INFO -- Print information about an aperture. + +procedure ap_info (ap) + +pointer ap # Aperture pointer + +int n, ic_geti(), strlen() +real ic_getr() +pointer sp, str1, str2 + +begin + call smark (sp) + + if (AP_IC(ap) != NULL) { + call salloc (str1, SZ_LINE, TY_CHAR) + call salloc (str2, SZ_LINE, TY_CHAR) + + n = 0 + call ic_gstr (AP_IC(ap), "function", Memc[str1], SZ_LINE) + call sprintf (Memc[str2], SZ_LINE, "background: func=%s ord=%d") + call pargstr (Memc[str1]) + call pargi (ic_geti (AP_IC(ap), "order")) + n = strlen (Memc[str2]) + call printf ("%s") + call pargstr (Memc[str2]) + + call ic_gstr (AP_IC(ap), "sample", Memc[str1], SZ_LINE) + if (Memc[str1] != '*') { + call sprintf (Memc[str2], SZ_LINE, " sample=\"%s\"") + call pargstr (Memc[str1]) + n = n + strlen (Memc[str2]) + if (n > 80) { + call printf ("\n\t") + n = 8 + strlen (Memc[str2]) + } + call printf ("%s") + call pargstr (Memc[str2]) + } + if (ic_geti (AP_IC(ap), "naverage") != 1) { + call sprintf (Memc[str2], SZ_LINE, " nav=%d") + call pargi (ic_geti (AP_IC(ap), "naverage")) + n = n + strlen (Memc[str2]) + if (n > 80) { + call printf ("\n\t") + n = 8 + strlen (Memc[str2]) + } + call printf ("%s") + call pargstr (Memc[str2]) + } + if (ic_geti (AP_IC(ap), "niterate") > 0) { + call sprintf (Memc[str2], SZ_LINE, " nit=%d") + call pargi (ic_geti (AP_IC(ap), "niterate")) + n = n + strlen (Memc[str2]) + if (n > 80) { + call printf ("\n\t") + n = 8 + strlen (Memc[str2]) + } + call printf ("%s") + call pargstr (Memc[str2]) + call sprintf (Memc[str2], SZ_LINE, " low=%3.1f") + call pargr (ic_getr (AP_IC(ap), "low")) + n = n + strlen (Memc[str2]) + if (n > 80) { + call printf ("\n\t") + n = 8 + strlen (Memc[str2]) + } + call printf ("%s") + call pargstr (Memc[str2]) + call sprintf (Memc[str2], SZ_LINE, " high=%3.1f") + call pargr (ic_getr (AP_IC(ap), "high")) + n = n + strlen (Memc[str2]) + if (n > 80) { + call printf ("\n\t") + n = 8 + strlen (Memc[str2]) + } + call printf ("%s") + call pargstr (Memc[str2]) + if (ic_getr (AP_IC(ap), "grow") > 0) { + call sprintf (Memc[str2], SZ_LINE, " grow=%d") + call pargr (ic_getr (AP_IC(ap), "grow")) + n = n + strlen (Memc[str2]) + if (n > 80) { + call printf ("\n\t") + n = 8 + strlen (Memc[str2]) + } + call printf ("%s") + call pargstr (Memc[str2]) + } + } + call printf ("\n") + } + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apio.x b/noao/twodspec/apextract/apio.x new file mode 100644 index 00000000..bfd2c6e6 --- /dev/null +++ b/noao/twodspec/apextract/apio.x @@ -0,0 +1,144 @@ +include <time.h> + +# AP_LOG -- Verbose, log, and error output. + +procedure ap_log (str, log, verbose, err) + +char str[ARB] # String +int log # Write to log if logfile defined? +int verbose # Write to stdout if verbose? +int err # Write to stdout? + +int fd, open() +long clktime() +bool clgetb() +pointer sp, logfile, date +errchk open + +begin + call smark (sp) + call salloc (logfile, SZ_LINE, TY_CHAR) + call salloc (date, SZ_DATE, TY_CHAR) + call cnvdate (clktime(0), Memc[date], SZ_DATE) + + if (err == YES || (verbose == YES && clgetb ("verbose"))) { + call printf ("%s: %s\n") + call pargstr (Memc[date]) + call pargstr (str) + call flush (STDOUT) + } + + if (log == YES) { + call clgstr ("logfile", Memc[logfile], SZ_FNAME) + if (Memc[logfile] != EOS) { + fd = open (Memc[logfile], APPEND, TEXT_FILE) + call fprintf (fd, "%s: %s\n") + call pargstr (Memc[date]) + call pargstr (str) + call flush (fd) + call close (fd) + } + } + + call sfree (sp) +end + + +# AP_GOPEN/AP_GCLOSE -- Open and close the graphics device. +# The device "stdgraph" is used. + +procedure ap_gopen (gp) + +pointer gp # GIO pointer +pointer gplast # Last GIO pointer + +int flag +pointer gopen() +errchk gopen + +data flag/NO/ +common /apgio/ gplast + +begin + if (flag == NO) { + flag = YES + call ap_gclose () + } + + if (gplast == NULL) + gplast = gopen ("stdgraph", NEW_FILE, STDGRAPH) + + gp = gplast +end + +procedure ap_gclose () + +int flag +pointer gplast + +data flag/NO/ +common /apgio/ gplast + +begin + if (flag == NO) { + flag = YES + gplast = NULL + } + + if (gplast != NULL) { + call gclose (gplast) + gplast = NULL + } +end + + +# AP_POPEN -- Open the plot device or metacode file. This includes CLIO +# to get the plot device. + +procedure ap_popen (gp, fd, type) + +pointer gp # GIO pointer +int fd # FIO channel for metacode file +char type[ARB] # Plot type + +bool streq(), strne() +int open(), nowhite(), strncmp() +pointer sp, str, gopen() +errchk gopen, open + +begin + call smark (sp) + call salloc (str, SZ_FNAME, TY_CHAR) + call clgstr ("plotfile", Memc[str], SZ_LINE) + + gp = NULL + fd = NULL + if (nowhite (Memc[str], Memc[str], SZ_FNAME) > 0) { + if (strncmp ("debug", Memc[str], 5) == 0) { + if (streq (type, Memc[str+5]) || streq ("all", Memc[str+5])) { + fd = open (Memc[str], APPEND, BINARY_FILE) + gp = gopen ("stdvdm", APPEND, fd) + } + } else if (strne ("fits", type)) { + fd = open (Memc[str], APPEND, BINARY_FILE) + gp = gopen ("stdvdm", APPEND, fd) + } + } + + call sfree (sp) +end + + +# AP_PCLOSE -- Close plot file. + +procedure ap_pclose (gp, fd) + +pointer gp # GIO pointer +int fd # FIO channel for metacode file + +begin + if (gp != NULL) + call gclose (gp) + if (fd != NULL) + call close (fd) +end diff --git a/noao/twodspec/apextract/apmask.par b/noao/twodspec/apextract/apmask.par new file mode 100644 index 00000000..7f8e114b --- /dev/null +++ b/noao/twodspec/apextract/apmask.par @@ -0,0 +1,19 @@ +# APMASK + +input,s,a,,,,List of input images +output,s,a,,,,List of output masks +apertures,s,h,"",,,Apertures +references,s,h,"",,,List of reference images + +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,no,,,Recenter apertures? +resize,b,h,no,,,Resize apertures? +edit,b,h,yes,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,Fit the traced points interactively? +mask,b,h,yes,,,"Create mask images? +" +line,i,h,INDEF,1,,Starting dispersion line +nsum,i,h,10,,,Number of dispersion lines to sum or median +buffer,r,h,0.,,,Buffer distance from apertures diff --git a/noao/twodspec/apextract/apmask.x b/noao/twodspec/apextract/apmask.x new file mode 100644 index 00000000..4dc4da19 --- /dev/null +++ b/noao/twodspec/apextract/apmask.x @@ -0,0 +1,155 @@ +include <imhdr.h> +include <pmset.h> +include "apertures.h" + +# AP_MASK -- Create an aperture mask. +# The mask is boolean with pixels within the apertures having value 1 and +# pixels outside the mask having values 0. An additional buffer distance +# may be specified. + +procedure ap_mask (image, output, aps, naps) + +char image[SZ_FNAME] # Image name +char output[SZ_FNAME] # Output mask name +pointer aps[ARB] # Apertures +int naps # Number of apertures + +real buffer # Buffer distance + +int i, j, aaxis, baxis, nc, nl, na, nb, apmin, apmax, low, high +real aplow, aphigh, shift +long v[2] +short val +pointer im, pm, ap, cv, a1, b1 +pointer sp, name, str, buf, a, b, amin, bmax + +real clgetr(), ap_cveval() +bool ap_answer() +pointer ap_immap(), pm_newmask() +errchk ap_immap, pm_savef + +begin + # Query user. + call smark (sp) + call salloc (name, SZ_LINE, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + call sprintf (Memc[str], SZ_LINE, "Create aperture mask for %s?") + call pargstr (image) + if (!ap_answer ("ansmask", Memc[str])) { + call sfree (sp) + return + } + + # Get buffer distance. + buffer = clgetr ("buffer") + + # Make the image and initialize the mask. + im = ap_immap (image, aaxis, baxis) + pm = pm_newmask (im, 1) + nc = IM_LEN(im,1) + nl = IM_LEN(im,2) + na = IM_LEN(im,aaxis) + nb = IM_LEN(im,baxis) + + # Allocate memory. + call salloc (buf, nc, TY_SHORT) + call salloc (a, naps*nb, TY_SHORT) + call salloc (b, naps*nb, TY_SHORT) + call salloc (amin, naps, TY_SHORT) + call salloc (bmax, naps, TY_SHORT) + val = 1 + + # Go through and compute all the limits as well as the maximum + # range of each aperture. This information must be computed for + # an aperture axis of 2 and it is also done for aperture axis + # of 1 just to keep the code the same. + + do i = 1, naps { + ap = aps[i] + cv = AP_CV(ap) + aplow = AP_CEN(ap,aaxis) + AP_LOW(ap,aaxis) - buffer + aphigh = AP_CEN(ap,aaxis) + AP_HIGH(ap,aaxis) + buffer + apmin = aplow + apmax = aphigh + a1 = a + (i - 1) * nb + b1 = b + (i - 1) * nb + do j = 1, nb { + shift = ap_cveval (cv, real (j)) + low = nint (aplow + shift) + high = nint (aphigh + shift) + Mems[a1+j-1] = low + Mems[b1+j-1] = high + apmin = min (low, apmin) + apmax = max (high, apmax) + } + Mems[amin+i-1] = apmin + Mems[bmax+i-1] = apmax + } + + # For each line create a pixel array mask. For aperture axis 1 this + # is simple while for aperture axis 2 we have to look through each + # line to see if any apertures intersect the line. + + switch (aaxis) { + case 1: + do j = 1, nl { + v[2] = j + call aclrs (Mems[buf], nc) + a1 = a + j - 1 + b1 = b + j - 1 + do i = 1, naps { + low = Mems[a1] + high = Mems[b1] + low = max (1, low) + high = min (na, high) + if (low <= high) + call amovks (val, Mems[buf+low-1], high-low+1) + a1 = a1 + nb + b1 = b1 + nb + } + call pmplps (pm, v, Mems[buf], 1, nc, PIX_SRC) + } + case 2: + do j = 1, nl { + v[2] = j + call aclrs (Mems[buf], nc) + do i = 1, naps { + if (j < Mems[amin+i-1] || j > Mems[bmax+i-1]) + next + + a1 = a + (i - 1) * nb + b1 = b + (i - 1) * nb + for (low=0; low<nb; low=low+1) { + if (j < Mems[a1+low] || j > Mems[b1+low]) + next + for (high=low+1; high<nb; high=high+1) + if (j < Mems[a1+high] || j > Mems[b1+high]) + break + call amovks (val, Mems[buf+low], high-low) + low = high - 1 + } + } + call pmplps (pm, v, Mems[buf], 1, nc, PIX_SRC) + } + } + + # Log the output and finish up. + if (output[1] == EOS) { + call sprintf (Memc[name], SZ_LINE, "%s.pl") + call pargstr (image) + } else + call strcpy (output, Memc[name], SZ_LINE) + call sprintf (Memc[str], SZ_LINE, "Aperture mask for %s") + call pargstr (image) + + call pm_savef (pm, Memc[name], Memc[str], 0) + call pm_close (pm) + call imunmap (im) + + call sprintf (Memc[str], SZ_LINE, "MASK - Aperture mask for %s --> %s") + call pargstr (image) + call pargstr (Memc[name]) + call ap_log (Memc[str], YES, YES, NO) + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apmw.x b/noao/twodspec/apextract/apmw.x new file mode 100644 index 00000000..9fcd35d7 --- /dev/null +++ b/noao/twodspec/apextract/apmw.x @@ -0,0 +1,280 @@ +include <error.h> +include <imhdr.h> +include <imio.h> +include <mwset.h> + + +# APMW_OPEN -- Open APMW structure. +# APMW_CLOSE -- Close APMW structure. +# APMW_SETAP -- Set aperture values in APMW structure. +# APMW_SAVEIM -- Set WCS in image header. +# APMW_WCSFIX -- Fix up WCS + +# Output formats +define ONEDSPEC 1 # Individual 1D spectra +define MULTISPEC 2 # Multiple spectra +define ECHELLE 3 # Echelle spectra +define STRIP 4 # Strip spectra +define NORM 5 # Normalized spectra +define FLAT 6 # Flat spectra +define RATIO 7 # Ratio of data to model +define DIFF 8 # Difference of data and model +define FIT 9 # Model +define NOISE 10 # Noise calculation + + +# Data structure for the apertures. This version assumes the coordinates +# are the same for all the apertures. + +define APMW_LEN (8 + $1 * 6) # Structure length + +define APMW_LABEL Memi[$1] # WCS label +define APMW_UNITS Memi[$1+1] # WCS units +define APMW_DTYPE Memi[$1+2] # Dispersion type +define APMW_NW Memi[$1+3] # Number of pixels +define APMW_W1 Memd[P2D($1+4)] # Starting coordinate +define APMW_DW Memd[P2D($1+6)] # Coordinate per pixel +define APMW_AP Memi[$1+6*($2-1)+8] # Aperture +define APMW_BEAM Memi[$1+6*($2-1)+9] # Beam +define APMW_APLOW Memd[P2D($1+6*($2-1)+10)] # Aperture low +define APMW_APHIGH Memd[P2D($1+6*($2-1)+12)] # Aperture high + + +# APMW_OPEN -- Open APMW structure. + +pointer procedure apmw_open (in, out, dispaxis, naps, nw) + +pointer in #I Input IMIO pointer +pointer out #I Output IMIO pointer +int dispaxis #I Input dispersion axis +int naps #I Number of apertures +int nw #I Number of dispersion pixels +pointer apmw #O Returned APMW pointer + +int imgeti() +double mw_c1trand() +pointer mw, ct, mw_openim(), mw_sctran() +errchk mw_openim, mw_sctran, mw_c1trand, apmw_wcsfix + +begin + # Allocate data structure. + call malloc (apmw, APMW_LEN(naps), TY_STRUCT) + call malloc (APMW_LABEL(apmw), SZ_LINE, TY_CHAR) + call malloc (APMW_UNITS(apmw), SZ_LINE, TY_CHAR) + + # Set defaults. + call strcpy ("Pixel", Memc[APMW_LABEL(apmw)], SZ_LINE) + Memc[APMW_UNITS(apmw)] = EOS + APMW_DTYPE(apmw,i) = -1 + APMW_NW(apmw,i) = nw + APMW_W1(apmw,i) = 1. + APMW_DW(apmw,i) = 1. + + # Get WCS info from input image. + iferr { + mw = mw_openim (in) + iferr (APMW_DTYPE(apmw) = imgeti (in, "DC-FLAG")) + APMW_DTYPE(apmw) = -1 + iferr (call mw_gwattrs (mw, dispaxis, "label", + Memc[APMW_LABEL(apmw)], SZ_LINE)) { + if (APMW_DTYPE(apmw) == -1) + call strcpy ("Pixel", Memc[APMW_LABEL(apmw)], SZ_LINE) + else + call strcpy ("Wavelength", Memc[APMW_LABEL(apmw)], SZ_LINE) + } + iferr (call mw_gwattrs (mw, dispaxis, "units", + Memc[APMW_UNITS(apmw)], SZ_LINE)) { + if (APMW_DTYPE(apmw) == -1) + Memc[APMW_UNITS(apmw)] = EOS + else + call strcpy ("Angstroms", Memc[APMW_UNITS(apmw)], SZ_LINE) + } + + call apmw_wcsfix (in, mw) + iferr (ct = mw_sctran (mw, "logical", "world", dispaxis)) + call error (1, + "Coordinate system ignored (rotated?). Using pixel coordinates.") + APMW_W1(apmw) = mw_c1trand (ct, 1D0) + APMW_DW(apmw) = mw_c1trand (ct, double (nw)) + APMW_DW(apmw) = (APMW_DW(apmw)-APMW_W1(apmw))/(nw-1) + } then + call erract (EA_WARN) + + call mw_close (mw) + + return (apmw) +end + + +# APMW_CLOSE -- Close APMW structure. + +procedure apmw_close (apmw) + +pointer apmw # APMW pointer + +begin + call mfree (APMW_LABEL(apmw), TY_CHAR) + call mfree (APMW_UNITS(apmw), TY_CHAR) + call mfree (apmw, TY_STRUCT) +end + + +# APMW_SETAP -- Set aperture values in APMW structure. + +procedure apmw_setap (apmw, line, ap, beam, aplow, aphigh) + +pointer apmw # APMW pointer +int line # Image line +int ap # Aperture +int beam # Beam +real aplow # Aperture lower limit +real aphigh # Aperture upper limit + +begin + APMW_AP(apmw,line) = ap + APMW_BEAM(apmw,line) = beam + APMW_APLOW(apmw,line) = aplow + APMW_APHIGH(apmw,line) = aphigh +end + + +# APMW_SAVEIM -- Save WCS in image header. + +procedure apmw_saveim (apmw, im, fmt) + +pointer apmw #I APMW pointer +pointer im #I IMIO pointer +int fmt #I Output format + +int i, naps, wcsdim, axes[3], imaccf() +double r[3], w[3], cd[9] +bool strne() +pointer sp, key, str, mw, list, mw_open(), imofnlu(), imgnfn() +errchk imdelf +data axes/1,2,3/ + +begin + call smark (sp) + call salloc (key, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + + if (fmt == STRIP) + naps = 1 + else + naps = IM_LEN(im, 2) + + # Workaround for truncation of header during image header copy. + IM_HDRLEN(im) = IM_LENHDRMEM(im) + + # Delete keywords. + list = imofnlu (im, "SLFIB[0-9]*") + while (imgnfn (list, Memc[key], SZ_FNAME) != EOF) + call imdelf (im, Memc[key]) + call imcfnl (list) + + # Add aperture parameters to image header. + do i = 1, naps { + call sprintf (Memc[key], SZ_FNAME, "APNUM%d") + call pargi (i) + call sprintf (Memc[str], SZ_LINE, "%d %d %.2f %.2f") + call pargi (APMW_AP(apmw,i)) + call pargi (APMW_BEAM(apmw,i)) + call pargd (APMW_APLOW(apmw,i)) + call pargd (APMW_APHIGH(apmw,i)) + call imastr (im, Memc[key], Memc[str]) + if (naps == 1) { + call sprintf (Memc[key], SZ_FNAME, "APID%d") + call pargi (i) + ifnoerr (call imgstr (im, Memc[key], Memc[str], SZ_LINE)) { + if (strne (Memc[str], IM_TITLE(im))) { + call imastr (im, "MSTITLE", IM_TITLE(im)) + call strcpy (Memc[str], IM_TITLE(im), SZ_IMTITLE) + } + call imdelf (im, Memc[key]) + } + } + } + + # Add dispersion parameters to image header. + if (APMW_DTYPE(apmw) != -1) + call imaddi (im, "DC-FLAG", APMW_DTYPE(apmw)) + else if (imaccf (im, "DC-FLAG") == YES) + call imdelf (im, "DC-FLAG") + if (APMW_NW(apmw) < IM_LEN(im,1)) + call imaddi (im, "NP2", APMW_NW(apmw)) + else if (imaccf (im, "NP2") == YES) + call imdelf (im, "NP2") + iferr (call imdelf (im, "dispaxis")) + ; + if (fmt == STRIP) + call imaddi (im, "dispaxis", 1) + + # Set WCS in image header. + wcsdim = IM_NPHYSDIM(im) + mw = mw_open (NULL, wcsdim) + if (fmt == STRIP) + call mw_newsystem (mw, "linear", wcsdim) + else + call mw_newsystem (mw, "equispec", wcsdim) + call mw_swtype (mw, axes, wcsdim, "linear", "") + if (Memc[APMW_LABEL(apmw)] != EOS) + call mw_swattrs (mw, 1, "label", Memc[APMW_LABEL(apmw)]) + if (Memc[APMW_UNITS(apmw)] != EOS) + call mw_swattrs (mw, 1, "units", Memc[APMW_UNITS(apmw)]) + + call aclrd (r, 3) + call aclrd (w, 3) + call aclrd (cd, 9) + r[1] = 1. + w[1] = APMW_W1(apmw) + cd[1] = APMW_DW(apmw) + if (wcsdim == 2) + cd[4] = 1. + if (wcsdim == 3) { + cd[5] = 1. + cd[9] = 1. + } + call mw_swtermd (mw, r, w, cd, wcsdim) + + call mw_saveim (mw, im) + call mw_close (mw) + + call sfree (sp) +end + + +# APMW_WCSFIX -- Fix up WCS to avoid CDELT=0 which occurs if there are WCS +# keywords in the header but no CDELT. + +procedure apmw_wcsfix (im, mw) + +pointer im # IMIO pointer +pointer mw # MWCS pointer + +int i, ndim, mw_stati() +double val +pointer sp, r, w, cd +errchk mw_gwtermd, mw_swtermd + +begin + call mw_seti (mw, MW_USEAXMAP, NO) + ndim = mw_stati (mw, MW_NDIM) + + call smark (sp) + call salloc (r, ndim, TY_DOUBLE) + call salloc (w, ndim, TY_DOUBLE) + call salloc (cd, ndim*ndim, TY_DOUBLE) + + # Check cd terms. Assume no rotation. + call mw_gwtermd (mw, Memd[r], Memd[w], Memd[cd], ndim) + do i = 0, ndim-1 { + val = Memd[cd+i*(ndim+1)] + if (val == 0D0) { + Memd[w+i] = 1D0 + Memd[cd+i*(ndim+1)] = 1D0 + } + } + call mw_swtermd (mw, Memd[r], Memd[w], Memd[cd], ndim) + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apnearest.x b/noao/twodspec/apextract/apnearest.x new file mode 100644 index 00000000..f3e027c5 --- /dev/null +++ b/noao/twodspec/apextract/apnearest.x @@ -0,0 +1,75 @@ +include <mach.h> +include "apertures.h" + +# AP_NEAREST -- Find the index of the aperture nearest cursor position x. + +define DELTA 0.01 # Tolerance for equidistant apertures + +procedure ap_nearest (index, line, aps, naps, x) + +int index # Index of aperture nearest x +int line # Dispersion line +pointer aps[ARB] # Aperture pointers +int naps # Number of apertures +real x # Point nearest aperture + +int i, j, apaxis +char ch +real d, delta +pointer ap + +int fscan(), nscan() +real ap_cveval() + +begin + if (naps == 0) + return + + index = 0 + delta = MAX_REAL + + for (i = 1; i <= naps; i = i + 1) { + ap = aps[i] + apaxis = AP_AXIS(ap) + d = abs (AP_CEN(ap, apaxis)+ap_cveval(AP_CV(ap),real(line))-x) + if (d < delta - DELTA) { + j = 1 + index = i + delta = d + } else if (d < delta + DELTA) + j = j + 1 + } + + # If there is more than one aperture equally near ask the user. + if (j > 1) { + call printf ("Apertures") + for (i = 1; i <= naps; i = i + 1) { + ap = aps[i] + apaxis = AP_AXIS(ap) + d = abs (AP_CEN(ap, apaxis)+ap_cveval(AP_CV(ap),real(line))-x) + if (d < delta + DELTA) { + call printf (" %d") + call pargi (AP_ID (ap)) + } + } + call printf (" are equally near the cursor.\n") +10 call printf ("Choose an aperture (%d): ") + call pargi (AP_ID (aps[index])) + call flush (STDOUT) + if (fscan (STDIN) != EOF) { + call scanc (ch) + if (ch == '\n') + return + + call reset_scan() + call gargi (j) + if (nscan() == 0) + goto 10 + for (i=1; (i<=naps)&&(AP_ID(aps[i])!=j); i=i+1) + ; + if (i > naps) + goto 10 + index = i + } + } +end diff --git a/noao/twodspec/apextract/apnoise.key b/noao/twodspec/apextract/apnoise.key new file mode 100644 index 00000000..4920453a --- /dev/null +++ b/noao/twodspec/apextract/apnoise.key @@ -0,0 +1,14 @@ + APNOISE CURSOR COMMANDS + + +? Print command help +q Quit +r Redraw +w Window the graph (see :/help) +I Interupt immediately + +:gain <value> Check or set the gain model parameter +:readnoise <value> Check or set the read noise model parameter + +Also see the CURSOR MODE commads (:.help) and the windowing commands +(:/help). diff --git a/noao/twodspec/apextract/apnoise.par b/noao/twodspec/apextract/apnoise.par new file mode 100644 index 00000000..365bc1c3 --- /dev/null +++ b/noao/twodspec/apextract/apnoise.par @@ -0,0 +1,30 @@ +# APSIGMA + +input,s,a,,,,List of images to evaluate +apertures,s,h,"",,,Apertures +references,s,h,"",,,"List of reference images +" +dmin,r,a,,,,Data minimum for sigma bins +dmax,r,a,,,,Data maximum for sigma bins +nbins,i,a,,1,,Number of sigma bins +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,yes,,,Recenter apertures? +resize,b,h,yes,,,Resize apertures? +edit,b,h,yes,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,"Fit traced points interactively? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,10,,,Number of dispersion lines to sum or median +threshold,r,h,10.,,,"Division threshold for ratio fit +" +background,s,h,"none","none|average|median|minimum|fit",,Background to subtract +pfit,s,h,"fit1d","fit1d|fit2d",,Profile fitting type (fit1d|fit2d) +clean,b,h,no,,,Detect and replace bad pixels? +skybox,i,h,1,1,,Box car smoothing length for sky +saturation,r,h,INDEF,,,Saturation level +readnoise,s,h,"0.",,,Read out noise sigma (photons) +gain,s,h,"1.",,,Photon gain (photons/data number) +lsigma,r,h,4.,0.,,Lower rejection threshold +usigma,r,h,4.,0.,,Upper rejection threshold diff --git a/noao/twodspec/apextract/apnoise.x b/noao/twodspec/apextract/apnoise.x new file mode 100644 index 00000000..d22c09ae --- /dev/null +++ b/noao/twodspec/apextract/apnoise.x @@ -0,0 +1,256 @@ +include <gset.h> +include <pkg/gtools.h> +include "apertures.h" + + +# AP_NOISE -- Model residuals. + +procedure ap_noise (ap, gain, dbuf, nc, nl, c1, l1, sbuf, spec, profile, nx, ny, + xs, ys, sum2, sum4, nsum, nbin, dmin, dmax) + +pointer ap # Aperture structure +real gain # Gain +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +pointer sbuf # Sky buffer (NULL if no sky) +real spec[ny] # Normalization spectrum +real profile[ny,nx] # Profile +int nx, ny # Size of profile array +int xs[ny], ys # Start of spectrum in image +real sum2[nbin] # Sum of residuals squared in bin +real sum4[nbin] # Sum of residuals squared in bin +int nsum[nbin] # Number of values in bin +int nbin # Number of bins +real dmin, dmax # Data limits of bins + +int i, ix, iy, ix1, ix2 +real dstep, low, high, s, x1, x2, model, data, ap_cveval() +pointer cv, sptr, dptr + +begin + dstep = (dmax - dmin) / nbin + + i = AP_AXIS(ap) + low = AP_CEN(ap,i) + AP_LOW(ap,i) + high = AP_CEN(ap,i) + AP_HIGH(ap,i) + cv = AP_CV(ap) + + do iy = 1, ny { + i = iy + ys - 1 + s = ap_cveval (cv, real (i)) + x1 = max (0.5, low + s) + x2 = min (c1 + nc - 0.49, high + s) + if (x1 > x2) + next + + ix1 = nint (x1) - xs[iy] + 1 + ix2 = nint (x2) - xs[iy] + 1 + + s = spec[iy] + if (sbuf != NULL) + sptr = sbuf + (iy - 1) * nx - 1 + dptr = dbuf + (i - l1) * nc + nint(x1) - c1 + do ix = ix1, ix2 { + if (sbuf != NULL) { + model = (s * profile[iy,ix] + Memr[sptr]) / gain + sptr = sptr + 1 + } else + model = (s * profile[iy,ix]) / gain + data = Memr[dptr] / gain + dptr = dptr + 1 + + if (model < dmin || model >= dmax) + next + i = (model - dmin) / dstep + 1 + sum2[i] = sum2[i] + (data - model) ** 2 + sum4[i] = sum4[i] + (data - model) ** 4 + nsum[i] = nsum[i] + 1 + } + } +end + + +define HELP "noao$twodspec/apextract/apnoise.key" +define PROMPT "apextract options" + +# AP_NPLOT -- Plot and examine noise characteristics. + +procedure ap_nplot (image, im, sigma, sigerr, npts, dmin, dmax) + +char image[SZ_FNAME] # Image +pointer im # Image pointer +real sigma[npts] # Sigma values +real sigerr[npts] # Sigma errors +int npts # Number of sigma values +real dmin, dmax # Data min and max + +real rdnoise # Read noise +real gain # Gain + +int i, newgraph, wcs, key +real wx, wy, x, x1, x2, dx, y, ymin, ymax +pointer sp, cmd, gp, gt + +int gt_gcur() +real apgimr() +#int apgwrd() +#bool ap_answer() +pointer gt_init() +errchk ap_gopen + +begin + # Query user. + call smark (sp) + call salloc (cmd, SZ_LINE, TY_CHAR) + #call sprintf (Memc[cmd], SZ_LINE, "Edit apertures for %s?") + # call pargstr (image) + #if (!ap_answer ("ansedit", Memc[cmd])) { + # call sfree (sp) + # return + #} + + gain = apgimr ("gain", im) + rdnoise = apgimr ("readnoise", im) + + dx = (dmax - dmin) / npts + x1 = dmin + dx / 2 + x2 = dmax - dx / 2 + ymin = sigma[1] - sigerr[1] + ymax = sigma[1] + sigerr[1] + do i = 2, npts { + ymin = min (ymin, sigma[i] - sigerr[i]) + ymax = max (ymax, sigma[i] + sigerr[i]) + } + + # Set up the graphics. + call sprintf (Memc[cmd], SZ_LINE, "Noise characteristics of image %s") + call pargstr (image) + call ap_gopen (gp) + gt = gt_init() + call gt_sets (gt, GTTITLE, Memc[cmd]) + call gt_sets (gt, GTXLABEL, "Data value") + call gt_sets (gt, GTYLABEL, "Sigma") + call gt_sets (gt, GTTYPE, "mark") + call gt_sets (gt, GTMARK, "plus") + + # Enter cursor loop. + key = 'r' + repeat { + switch (key) { + case '?': # Print help text. + call gpagefile (gp, HELP, PROMPT) + + case ':': # Colon commands. + if (Memc[cmd] == '/') + call gt_colon (Memc[cmd], gp, gt, newgraph) + else + call ap_ncolon (Memc[cmd], rdnoise, gain, newgraph) + + case 'q': + break + + case 'r': # Redraw the graph. + newgraph = YES + + case 'w': # Window graph + call gt_window (gt, gp, "gcur", newgraph) + + case 'I': # Interrupt + call fatal (0, "Interrupt") + + default: # Ring bell for unrecognized commands. + call printf ("\007") + } + + # Update the graph if needed. + if (newgraph == YES) { + call sprintf (Memc[cmd], SZ_LINE, + "Read noise = %g e-, Gain = %g e-/DN") + call pargr (rdnoise) + call pargr (gain) + call gt_sets (gt, GTPARAMS, Memc[cmd]) + + call gclear (gp) + y = sqrt ((rdnoise/gain)**2 + dmax/gain) + call gswind (gp, dmin, dmax, ymin, max (ymax, y)) + call gt_swind (gp, gt) + call gt_labax (gp, gt) + do i = 1, npts { + if (sigma[i] > 0) { + x = x1 + (i-1) * dx + call gmark (gp, x, sigma[i], GM_VEBAR+GM_HLINE, -dx/2, + -sigerr[i]) + } + } + do i = 1, npts { + x = x1 + (i-1) * dx + y = sqrt ((rdnoise/gain)**2 + x/gain) + if (i == 1) + call gamove (gp, x, y) + else + call gadraw (gp, x, y) + } + newgraph = NO + } + + } until (gt_gcur ("gcur", wx, wy, wcs, key, Memc[cmd], SZ_LINE) == EOF) + + # Free memory. + call gt_free (gt) + call sfree (sp) +end + + +# List of colon commands. +define CMDS "|readnoise|gain|" +define RDNOISE 1 # Read noise +define GAIN 2 # Gain + +# AP_NCOLON -- Respond to colon command from ap_nplot. + +procedure ap_ncolon (command, rdnoise, gain, newgraph) + +char command[ARB] # Colon command +real rdnoise # Readout noise +real gain # Gain +int newgraph # New graph? + +real rval +int ncmd, nscan(), strdic() +pointer sp, cmd + +begin + # Scan the command string and get the first word. + call smark (sp) + call salloc (cmd, SZ_LINE, TY_CHAR) + + call sscan (command) + call gargwrd (cmd, SZ_LINE) + ncmd = strdic (cmd, cmd, SZ_LINE, CMDS) + + switch (ncmd) { + case RDNOISE: + call gargr (rval) + if (nscan() == 2) { + rdnoise = rval + newgraph = YES + } else { + call printf ("rdnoise %g\n") + call pargr (rdnoise) + } + case GAIN: + call gargr (rval) + if (nscan() == 2) { + gain = rval + newgraph = YES + } else { + call printf ("gain %g\n") + call pargr (gain) + } + default: + call printf ("Unrecognized or ambiguous command\007") + } + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apnoise1.par b/noao/twodspec/apextract/apnoise1.par new file mode 100644 index 00000000..3b5532a7 --- /dev/null +++ b/noao/twodspec/apextract/apnoise1.par @@ -0,0 +1,118 @@ +# OUTPUT PARAMETERS + +apertures,s,h,)apall.apertures,,,>apnoise.apertures +format,s,h,)apsum.format,,,>apsum.format +extras,b,h,)apsum.extras,,,>apsum.extras +dbwrite,s,h,yes,,,Write to database? +initialize,b,h,yes,,,Initialize answers? +verbose,b,h,)_.verbose,,,"Verbose output? + +# DEFAULT APERTURE PARAMETERS +" +lower,r,h,)apdefault.lower,,,>apdefault.lower +upper,r,h,)apdefault.upper,,,>apdefault.upper +apidtable,s,h,)apdefault.apidtable,,,">apdefault.apidtable + +# DEFAULT BACKGROUND PARAMETERS +" +b_function,s,h,)apdefault.b_function,,,>apdefault.b_function +b_order,i,h,)apdefault.b_order,,,>apdefault.b_order +b_sample,s,h,)apdefault.b_sample,,,>apdefault.b_sample +b_naverage,i,h,)apdefault.b_naverage,,,>apdefault.b_naverage +b_niterate,i,h,)apdefault.b_niterate,,,>apdefault.b_niterate +b_low_reject,r,h,)apdefault.b_low_reject,,,>apdefault.b_low_reject +b_high_reject,r,h,)apdefault.b_high_reject,,,>apdefault.b_high_reject +b_grow,r,h,)apdefault.b_grow,,,">apdefault.b_grow + +# APERTURE CENTERING PARAMETERS +" +width,r,h,)apedit.width,,,>apedit.width +radius,r,h,)apedit.radius,,,>apedit.radius +threshold,r,h,)apedit.threshold,,,">apedit.threshold + +# AUTOMATIC FINDING AND ORDERING PARAMETERS +" +nfind,i,h,)apfind.nfind,,,>apfind.nfind +minsep,r,h,)apfind.minsep,,,>apfind.minsep +maxsep,r,h,)apfind.maxsep,,,>apfind.maxsep +order,s,h,)apfind.order,,,">apfind.order + +# RECENTERING PARAMETERS +" +aprecenter,s,h,)aprecenter.aprecenter,,,>aprecenter.aprecenter +npeaks,r,h,)aprecenter.npeaks,,,>aprecenter.npeaks +shift,b,h,)aprecenter.shift,,,">aprecenter.shift + +# RESIZING PARAMETERS +" +llimit,r,h,)apresize.llimit,,,>apresize.llimit +ulimit,r,h,)apresize.ulimit,,,>apresize.ulimit +ylevel,r,h,)apresize.ylevel,,,>apresize.ylevel +peak,b,h,)apresize.peak,,,>apresize.peak +bkg,b,h,)apresize.bkg,,,>apresize.bkg +r_grow,r,h,)apresize.r_grow,,,>apresize.r_grow +avglimits,b,h,)apresize.avglimits,,,">apresize.avglimits + +# EDITING PARAMETERS +" +e_output,s,q,,,,Output spectra rootname +e_profiles,s,q,,,,Profile reference image + +# TRACING PARAMETERS +t_nsum,i,h,)aptrace.nsum,,,>aptrace.nsum +t_step,i,h,)aptrace.step,,,>aptrace.step +t_nlost,i,h,)aptrace.nlost,,,>aptrace.nlost +t_width,r,h,)apedit.width,,,>apedit.width +t_function,s,h,)aptrace.function,,,>aptrace.function +t_order,i,h,)aptrace.order,,,>aptrace.order +t_sample,s,h,)aptrace.sample,,,>aptrace.sample +t_naverage,i,h,)aptrace.naverage,,,>aptrace.naverage +t_niterate,i,h,)aptrace.niterate,,,>aptrace.niterate +t_low_reject,r,h,)aptrace.low_reject,,,>aptrace.low_reject +t_high_reject,r,h,)aptrace.high_reject,,,>aptrace.high_reject +t_grow,r,h,)aptrace.grow,,,">aptrace.grow + +# EXTRACTION PARAMETERS +" +background,s,h,)apnoise.background,,,>apnoise.background +skybox,i,h,)apnoise.skybox,,,>apnoise.skybox +weights,s,h,"none",,,Extraction weights (none|variance) +pfit,s,h,)apnoise.pfit,,,>apnoise.pfit +clean,b,h,)apnoise.clean,,,>apnoise.clean +nclean,r,h,0.5,,,Maximum number of pixels to clean +niterate,i,h,5,0,,Number of profile fitting iterations +saturation,r,h,)apnoise.saturation,,,>apnoise.saturation +readnoise,s,h,)apnoise.readnoise,,,>apnoise.readnoise +gain,s,h,)apnoise.gain,,,>apnoise.gain +lsigma,r,h,)apnoise.lsigma,,,>apnoise.lsigma +usigma,r,h,)apnoise.usigma,,,>apnoise.usigma +polysep,r,h,0.90,0.1,0.95,Marsh algorithm polynomial spacing +polyorder,i,h,10,1,,Marsh algorithm polynomial order +nsubaps,i,h,1,,,"Number of subapertures per aperture + +# ANSWER PARAMETERS +" +ansclobber,s,h,"no",,," " +ansclobber1,s,h,"no",,," " +ansdbwrite,s,h,"yes",,," " +ansdbwrite1,s,h,"yes",,," " +ansedit,s,h,"yes",,," " +ansextract,s,h,"yes",,," " +ansfind,s,h,"yes",,," " +ansfit,s,h,"yes",,," " +ansfitscatter,s,h,"yes",,," " +ansfitsmooth,s,h,"yes",,," " +ansfitspec,s,h,"yes",,," " +ansfitspec1,s,h,"yes",,," " +ansfittrace,s,h,"yes",,," " +ansfittrace1,s,h,"yes",,," " +ansflat,s,h,"yes",,," " +ansmask,s,h,"yes",,," " +ansnorm,s,h,"yes",,," " +ansrecenter,s,h,"yes",,," " +ansresize,s,h,"yes",,," " +ansreview,s,h,"yes",,," " +ansreview1,s,h,"yes",,," " +ansscat,s,h,"yes",,," " +anssmooth,s,h,"yes",,," " +anstrace,s,h,"yes",,," " diff --git a/noao/twodspec/apextract/apnorm1.par b/noao/twodspec/apextract/apnorm1.par new file mode 100644 index 00000000..1a182dce --- /dev/null +++ b/noao/twodspec/apextract/apnorm1.par @@ -0,0 +1,118 @@ +# OUTPUT PARAMETERS + +apertures,s,h,)apall.apertures,,,>apnorm.apertures +format,s,h,)apsum.format,,,>apsum.format +extras,b,h,)apsum.extras,,,>apsum.extras +dbwrite,s,h,yes,,,Write to database? +initialize,b,h,yes,,,Initialize answers? +verbose,b,h,)_.verbose,,,"Verbose output? + +# DEFAULT APERTURE PARAMETERS +" +lower,r,h,)apdefault.lower,,,>apdefault.lower +upper,r,h,)apdefault.upper,,,>apdefault.upper +apidtable,s,h,)apdefault.apidtable,,,">apdefault.apidtable + +# DEFAULT BACKGROUND PARAMETERS +" +b_function,s,h,)apdefault.b_function,,,>apdefault.b_function +b_order,i,h,)apdefault.b_order,,,>apdefault.b_order +b_sample,s,h,)apdefault.b_sample,,,>apdefault.b_sample +b_naverage,i,h,)apdefault.b_naverage,,,>apdefault.b_naverage +b_niterate,i,h,)apdefault.b_niterate,,,>apdefault.b_niterate +b_low_reject,r,h,)apdefault.b_low_reject,,,>apdefault.b_low_reject +b_high_reject,r,h,)apdefault.b_high_reject,,,>apdefault.b_high_reject +b_grow,r,h,)apdefault.b_grow,,,">apdefault.b_grow + +# APERTURE CENTERING PARAMETERS +" +width,r,h,)apedit.width,,,>apedit.width +radius,r,h,)apedit.radius,,,>apedit.radius +threshold,r,h,)apedit.threshold,,,">apedit.threshold + +# AUTOMATIC FINDING AND ORDERING PARAMETERS +" +nfind,i,h,)apfind.nfind,,,>apfind.nfind +minsep,r,h,)apfind.minsep,,,>apfind.minsep +maxsep,r,h,)apfind.maxsep,,,>apfind.maxsep +order,s,h,)apfind.order,,,">apfind.order + +# RECENTERING PARAMETERS +" +aprecenter,s,h,)aprecenter.aprecenter,,,>aprecenter.aprecenter +npeaks,r,h,)aprecenter.npeaks,,,>aprecenter.npeaks +shift,b,h,)aprecenter.shift,,,">aprecenter.shift + +# RESIZING PARAMETERS +" +llimit,r,h,)apresize.llimit,,,>apresize.llimit +ulimit,r,h,)apresize.ulimit,,,>apresize.ulimit +ylevel,r,h,)apresize.ylevel,,,>apresize.ylevel +peak,b,h,)apresize.peak,,,>apresize.peak +bkg,b,h,)apresize.bkg,,,>apresize.bkg +r_grow,r,h,)apresize.r_grow,,,>apresize.r_grow +avglimits,b,h,)apresize.avglimits,,,">apresize.avglimits + +# EDITING PARAMETERS +" +e_output,s,q,,,,Output spectra rootname +e_profiles,s,q,,,,Profile reference image + +# TRACING PARAMETERS +t_nsum,i,h,)aptrace.nsum,,,>aptrace.nsum +t_step,i,h,)aptrace.step,,,>aptrace.step +t_nlost,i,h,)aptrace.nlost,,,>aptrace.nlost +t_width,r,h,)apedit.width,,,>apedit.width +t_function,s,h,)aptrace.function,,,>aptrace.function +t_order,i,h,)aptrace.order,,,>aptrace.order +t_sample,s,h,)aptrace.sample,,,>aptrace.sample +t_naverage,i,h,)aptrace.naverage,,,>aptrace.naverage +t_niterate,i,h,)aptrace.niterate,,,>aptrace.niterate +t_low_reject,r,h,)aptrace.low_reject,,,>aptrace.low_reject +t_high_reject,r,h,)aptrace.high_reject,,,>aptrace.high_reject +t_grow,r,h,)aptrace.grow,,,">aptrace.grow + +# EXTRACTION PARAMETERS +" +background,s,h,)apnorm.background,,,>apnorm.background +skybox,i,h,)apnorm.skybox,,,>apnorm.skybox +weights,s,h,)apnorm.weights,,,>apnorm.weights +pfit,s,h,)apnorm.pfit,,,>apnorm.pfit +clean,b,h,)apnorm.clean,,,>apnorm.clean +nclean,r,h,0.5,,,Maximum number of pixels to clean +niterate,i,h,5,0,,Number of profile fitting iterations +saturation,r,h,)apnorm.saturation,,,>apnorm.saturation +readnoise,s,h,)apnorm.readnoise,,,>apnorm.readnoise +gain,s,h,)apnorm.gain,,,>apnorm.gain +lsigma,r,h,)apnorm.lsigma,,,>apnorm.lsigma +usigma,r,h,)apnorm.usigma,,,>apnorm.usigma +polysep,r,h,0.90,0.1,0.95,Marsh algorithm polynomial spacing +polyorder,i,h,10,1,,Marsh algorithm polynomial order +nsubaps,i,h,1,,,"Number of subapertures per aperture + +# ANSWER PARAMETERS +" +ansclobber,s,h,"no",,," " +ansclobber1,s,h,"no",,," " +ansdbwrite,s,h,"yes",,," " +ansdbwrite1,s,h,"yes",,," " +ansedit,s,h,"yes",,," " +ansextract,s,h,"yes",,," " +ansfind,s,h,"yes",,," " +ansfit,s,h,"yes",,," " +ansfitscatter,s,h,"yes",,," " +ansfitsmooth,s,h,"yes",,," " +ansfitspec,s,h,"yes",,," " +ansfitspec1,s,h,"yes",,," " +ansfittrace,s,h,"yes",,," " +ansfittrace1,s,h,"yes",,," " +ansflat,s,h,"yes",,," " +ansmask,s,h,"yes",,," " +ansnorm,s,h,"yes",,," " +ansrecenter,s,h,"yes",,," " +ansresize,s,h,"yes",,," " +ansreview,s,h,"yes",,," " +ansreview1,s,h,"yes",,," " +ansscat,s,h,"yes",,," " +anssmooth,s,h,"yes",,," " +anstrace,s,h,"yes",,," " diff --git a/noao/twodspec/apextract/apnormalize.par b/noao/twodspec/apextract/apnormalize.par new file mode 100644 index 00000000..2fc64432 --- /dev/null +++ b/noao/twodspec/apextract/apnormalize.par @@ -0,0 +1,41 @@ +# APNORMALIZE + +input,s,a,,,,List of images to normalize +output,s,a,,,,List of output normalized images +apertures,s,h,"",,,Apertures +references,s,h,"",,,"List of reference images +" +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,yes,,,Recenter apertures? +resize,b,h,yes,,,Resize apertures? +edit,b,h,yes,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,Fit traced points interactively? +normalize,b,h,yes,,,Normalize spectra? +fitspec,b,h,yes,,,"Fit normalization spectra interactively? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,10,,,Number of dispersion lines to sum or median +cennorm,b,h,no,,,Normalize to the aperture center? +threshold,r,h,10.,,,"Threshold for normalization spectra +" +background,s,h,"none","none|average|median|minimum|fit",,Background to subtract +weights,s,h,"none","none|variance",,Extraction weights (none|variance) +pfit,s,h,"fit1d","fit1d|fit2d",,Profile fitting type (fit1d|fit2d) +clean,b,h,no,,,Detect and replace bad pixels? +skybox,i,h,1,1,,Box car smoothing length for sky +saturation,r,h,INDEF,,,Saturation level +readnoise,s,h,"0.",,,Read out noise sigma (photons) +gain,s,h,"1.",,,Photon gain (photons/data number) +lsigma,r,h,4.,0.,,Lower rejection threshold +usigma,r,h,4.,0.,,"Upper rejection threshold +" +function,s,h,"legendre","chebyshev|legendre|spline1|spline3",,Fitting function for normalization spectra +order,i,h,1,1,,Fitting function order +sample,s,h,"*",,,Sample regions +naverage,i,h,1,,,Average or median +niterate,i,h,0,0,,Number of rejection iterations +low_reject,r,h,3.,0.,,Lower rejection sigma +high_reject,r,h,3.,0.,,High upper rejection sigma +grow,r,h,0.,0.,,Rejection growing radius diff --git a/noao/twodspec/apextract/apparams.dat b/noao/twodspec/apextract/apparams.dat new file mode 100644 index 00000000..897e4f2e --- /dev/null +++ b/noao/twodspec/apextract/apparams.dat @@ -0,0 +1,68 @@ +"OUTPUT PARAMETERS" +format s %s 26 +extras b %b 26 +dbwrite s %s 26 + +"DEFAULT APERTURE PARAMETERS" +lower r %g 26 +upper r %g 26 +apidtable s %s 26 + +"DEFAULT BACKGROUND PARAMETERS" +b_function s %s 26 +b_order i %d 26 +b_sample s %s 26 +b_naverage i %d 26 +b_niterate i %d 26 +b_low_reject r %g 26 +b_high_reject r %g 26 +b_grow r %g 26 + +"APERTURE CENTERING PARAMETERS: FINDING, RECENTERING, MARKING" +width r %g 26 +radius r %g 26 +threshold r %g 26 + +"AUTOMATIC APERTURE FINDING AND ORDERING PARAMETERS" +minsep r %g 26 +maxsep r %g 26 +order s %s 26 + +"RECENTERING PARAMETERS" +apertures s %s 26 +npeaks r %g 26 +shift b %b 26 + +"RESIZING PARAMETERS" +llimit r %g 26 +ulimit r %g 26 +ylevel r %g 26 +peak b %b 26 +bkg b %b 26 +r_grow r %g 26 +avglimits b %b 26 + +"TRACING PARAMETERS" +t_nsum i %d 26 +t_step i %d 26 +t_width r %g 26 +t_function s %s 26 +t_order i %d 26 +t_sample s %s 26 +t_naverage i %d 26 +t_niterate i %d 26 +t_low_reject r %g 26 +t_high_reject r %g 26 +t_grow r %g 26 + +"EXTRACTION PARAMETERS" +weights s %s 26 +background s %s 26 +clean b %b 26 +saturation r %g 26 +readnoise r %g 26 +gain r %g 26 +lsigma r %g 26 +usigma r %g 26 +skybox i %d 26 +nsubaps i %d 26 diff --git a/noao/twodspec/apextract/apparams.h b/noao/twodspec/apextract/apparams.h new file mode 100644 index 00000000..ac3e37cb --- /dev/null +++ b/noao/twodspec/apextract/apparams.h @@ -0,0 +1,92 @@ +# PP_TABLE -- This table assigns pset pointers for each parameter. + +define PP_PP_LENTABLE 61 + +# APDEFAULT + +define PP_APIDTABLE Memi[$1] +define PP_LOWER Memi[$1+1] +define PP_UPPER Memi[$1+2] +define PP_B_FUNCTION Memi[$1+3] +define PP_B_ORDER Memi[$1+4] +define PP_B_SAMPLE Memi[$1+5] +define PP_B_NAVERAGE Memi[$1+6] +define PP_B_NITERATE Memi[$1+7] +define PP_B_LOW_REJECT Memi[$1+8] +define PP_B_HIGH_REJECT Memi[$1+9] +define PP_B_GROW Memi[$1+10] + +#APFIND + +define PP_NFIND Memi[$1+11] +define PP_MINSEP Memi[$1+12] +define PP_MAXSEP Memi[$1+13] +define PP_ORDER Memi[$1+14] + +# APRECENTER + +define PP_APERTURES Memi[$1+15] +define PP_NPEAKS Memi[$1+16] +define PP_SHIFT Memi[$1+17] + +# APRESIZE + +define PP_LLIMIT Memi[$1+18] +define PP_ULIMIT Memi[$1+19] +define PP_YLEVEL Memi[$1+20] +define PP_PEAK Memi[$1+21] +define PP_BKG Memi[$1+22] + +# APEDIT + +define PP_WIDTH Memi[$1+23] +define PP_RADIUS Memi[$1+24] +define PP_THRESHOLD Memi[$1+25] +define PP_E_OUTPUT Memi[$1+26] +define PP_E_SKY Memi[$1+27] +define PP_E_PROFILES Memi[$1+28] + +# APTRACE + +define PP_FITTRACE Memi[$1+29] +define PP_T_NSUM Memi[$1+30] +define PP_STEP Memi[$1+31] +define PP_T_FUNCTION Memi[$1+32] +define PP_T_ORDER Memi[$1+33] +define PP_T_SAMPLE Memi[$1+34] +define PP_T_NAVERAGE Memi[$1+35] +define PP_T_NITERATE Memi[$1+36] +define PP_T_LOW_REJECT Memi[$1+37] +define PP_T_HIGH_REJECT Memi[$1+38] +define PP_T_GROW Memi[$1+39] + +# APSUM or APSTRIP + +define PP_SKYEXTRACT Memi[$1+40] +define PP_BACKGROUND Memi[$1+41] +define PP_CLEAN Memi[$1+42] +define PP_WEIGHTS Memi[$1+43] +define PP_FIT(pp) Memi[$1+61] +define PP_NAVERAGE Memi[$1+44] +define PP_INTERPOLATOR Memi[$1+45] +define PP_NCLEAN Memi[$1+46] +define PP_LSIGMA Memi[$1+47] +define PP_USIGMA Memi[$1+48] +define PP_V0 Memi[$1+49] +define PP_V1 Memi[$1+50] + +# APNORMALIZE + +define PP_N_THRESHOLD Memi[$1+51] +define PP_N_FUNCTION Memi[$1+52] +define PP_N_ORDER Memi[$1+53] +define PP_N_SAMPLE Memi[$1+54] +define PP_N_NAVERAGE Memi[$1+55] +define PP_N_NITERATE Memi[$1+56] +define PP_N_LOW_REJECT Memi[$1+57] +define PP_N_HIGH_REJECT Memi[$1+58] +define PP_N_GROW Memi[$1+59] + +# APSCATTER + +define PP_BUFFER Memi[$1+60] diff --git a/noao/twodspec/apextract/apparams.par b/noao/twodspec/apextract/apparams.par new file mode 100644 index 00000000..61b2b2ce --- /dev/null +++ b/noao/twodspec/apextract/apparams.par @@ -0,0 +1,117 @@ +# OUTPUT PARAMETERS + +format,s,h,)apsum.format,,,>apsum.format +extras,b,h,)apsum.extras,,,>apsum.extras +dbwrite,s,h,yes,,,Write to database? +initialize,b,h,yes,,,Initialize answers? +verbose,b,h,)_.verbose,,,"Verbose output? + +# DEFAULT APERTURE PARAMETERS +" +lower,r,h,)apdefault.lower,,,>apdefault.lower +upper,r,h,)apdefault.upper,,,>apdefault.upper +apidtable,s,h,)apdefault.apidtable,,,">apdefault.apidtable + +# DEFAULT BACKGROUND PARAMETERS +" +b_function,s,h,)apdefault.b_function,,,>apdefault.b_function +b_order,i,h,)apdefault.b_order,,,>apdefault.b_order +b_sample,s,h,)apdefault.b_sample,,,>apdefault.b_sample +b_naverage,i,h,)apdefault.b_naverage,,,>apdefault.b_naverage +b_niterate,i,h,)apdefault.b_niterate,,,>apdefault.b_niterate +b_low_reject,r,h,)apdefault.b_low_reject,,,>apdefault.b_low_reject +b_high_reject,r,h,)apdefault.b_high_reject,,,>apdefault.b_high_reject +b_grow,r,h,)apdefault.b_grow,,,">apdefault.b_grow + +# APERTURE CENTERING PARAMETERS +" +width,r,h,)apedit.width,,,>apedit.width +radius,r,h,)apedit.radius,,,>apedit.radius +threshold,r,h,)apedit.threshold,,,">apedit.threshold + +# AUTOMATIC FINDING AND ORDERING PARAMETERS +" +nfind,i,h,)apfind.nfind,,,>apfind.nfind +minsep,r,h,)apfind.minsep,,,>apfind.minsep +maxsep,r,h,)apfind.maxsep,,,>apfind.maxsep +order,s,h,)apfind.order,,,">apfind.order + +# RECENTERING PARAMETERS +" +aprecenter,s,h,)aprecenter.aprecenter,,,>aprecenter.aprecenter +npeaks,r,h,)aprecenter.npeaks,,,>aprecenter.npeaks +shift,b,h,)aprecenter.shift,,,">aprecenter.shift + +# RESIZING PARAMETERS +" +llimit,r,h,)apresize.llimit,,,>apresize.llimit +ulimit,r,h,)apresize.ulimit,,,>apresize.ulimit +ylevel,r,h,)apresize.ylevel,,,>apresize.ylevel +peak,b,h,)apresize.peak,,,>apresize.peak +bkg,b,h,)apresize.bkg,,,>apresize.bkg +r_grow,r,h,)apresize.r_grow,,,>apresize.r_grow +avglimits,b,h,)apresize.avglimits,,,">apresize.avglimits + +# EDITING PARAMETERS +" +e_output,s,q,,,,Output spectra rootname +e_profiles,s,q,,,,Profile reference image + +# TRACING PARAMETERS +t_nsum,i,h,)aptrace.nsum,,,>aptrace.nsum +t_step,i,h,)aptrace.step,,,>aptrace.step +t_nlost,i,h,)aptrace.nlost,,,>aptrace.nlost +t_width,r,h,)apedit.width,,,>apedit.width +t_function,s,h,)aptrace.function,,,>aptrace.function +t_order,i,h,)aptrace.order,,,>aptrace.order +t_sample,s,h,)aptrace.sample,,,>aptrace.sample +t_naverage,i,h,)aptrace.naverage,,,>aptrace.naverage +t_niterate,i,h,)aptrace.niterate,,,>aptrace.niterate +t_low_reject,r,h,)aptrace.low_reject,,,>aptrace.low_reject +t_high_reject,r,h,)aptrace.high_reject,,,>aptrace.high_reject +t_grow,r,h,)aptrace.grow,,,">aptrace.grow + +# EXTRACTION PARAMETERS +" +background,s,h,)apsum.background,,,>apsum.background +skybox,i,h,)apsum.skybox,,,>apsum.skybox +weights,s,h,)apsum.weights,,,>apsum.weights +pfit,s,h,)apsum.pfit,,,>apsum.pfit +clean,b,h,)apsum.clean,,,>apsum.clean +nclean,r,h,0.5,,,Maximum number of pixels to clean +niterate,i,h,5,0,,Number of profile fitting iterations +saturation,r,h,)apsum.saturation,,,>apsum.saturation +readnoise,s,h,)apsum.readnoise,,,>apsum.readnoise +gain,s,h,)apsum.gain,,,>apsum.gain +lsigma,r,h,)apsum.lsigma,,,>apsum.lsigma +usigma,r,h,)apsum.usigma,,,>apsum.usigma +polysep,r,h,0.90,0.1,0.95,Marsh algorithm polynomial spacing +polyorder,i,h,10,1,,Marsh algorithm polynomial order +nsubaps,i,h,)apsum.nsubaps,,,">apsum.nsubaps + +# ANSWER PARAMETERS +" +ansclobber,s,h,"no",,," " +ansclobber1,s,h,"no",,," " +ansdbwrite,s,h,"yes",,," " +ansdbwrite1,s,h,"yes",,," " +ansedit,s,h,"yes",,," " +ansextract,s,h,"yes",,," " +ansfind,s,h,"yes",,," " +ansfit,s,h,"yes",,," " +ansfitscatter,s,h,"yes",,," " +ansfitsmooth,s,h,"yes",,," " +ansfitspec,s,h,"yes",,," " +ansfitspec1,s,h,"yes",,," " +ansfittrace,s,h,"yes",,," " +ansfittrace1,s,h,"yes",,," " +ansflat,s,h,"yes",,," " +ansmask,s,h,"yes",,," " +ansnorm,s,h,"yes",,," " +ansrecenter,s,h,"yes",,," " +ansresize,s,h,"yes",,," " +ansreview,s,h,"yes",,," " +ansreview1,s,h,"yes",,," " +ansscat,s,h,"yes",,," " +anssmooth,s,h,"yes",,," " +anstrace,s,h,"yes",,," " diff --git a/noao/twodspec/apextract/apparams.x b/noao/twodspec/apextract/apparams.x new file mode 100644 index 00000000..526b4bcd --- /dev/null +++ b/noao/twodspec/apextract/apparams.x @@ -0,0 +1,95 @@ +define PARAMS "apextract$apparams.dat" +define LEN_LINE 80 + +# AP_PARAMS -- Show the parameters. + +procedure ap_params (file, image, line, nsum) + +char file[ARB] # Aperture file +char image[ARB] # Image name +int line # Image line +int nsum # Number of lines to sum + +int in, out, len, nchar +pointer sp, param, type, format, instr, outstr, str +bool apgetb() +int apgeti(), open(), fscan(), nscan(), strlen() +real apgetr() +errchk open + +begin + # Open input parameter file and output stream. + in = open (PARAMS, READ_ONLY, TEXT_FILE) + out = open (file, APPEND, TEXT_FILE) + + call smark (sp) + call salloc (param, SZ_LINE, TY_CHAR) + call salloc (type, 10, TY_CHAR) + call salloc (format, 10, TY_CHAR) + call salloc (instr, SZ_LINE, TY_CHAR) + call salloc (outstr, SZ_LINE, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + Memc[outstr] = EOS + + call fprintf (out, "%32tAPEXTRACT PARAMETERS\n") + call fprintf (out, "image=%s%27tline=%d%53tnsum=%d\n") + call pargstr (image) + call pargi (line) + call pargi (nsum) + call fprintf (out, "database=%s%27tlogfile=%s%53tplotfile=%s\n\n") + call clgstr ("database", Memc[str], SZ_LINE) + call pargstr (Memc[str]) + call clgstr ("logfile", Memc[str], SZ_LINE) + call pargstr (Memc[str]) + call clgstr ("plotfile", Memc[str], SZ_LINE) + call pargstr (Memc[str]) + + len = 0 + while (fscan (in) != EOF) { + call gargwrd (Memc[param], SZ_LINE) + call gargwrd (Memc[type], 10) + call gargwrd (Memc[format], 10) + call gargi (nchar) + if (nscan() < 4) + nchar = LEN_LINE + + if (len + nchar > LEN_LINE) { + call strcat ("\n", Memc[outstr], SZ_LINE) + call fprintf (out, Memc[outstr]) + Memc[outstr] = EOS + len = 0 + } + + if (nscan() == 1) { + call sprintf (Memc[outstr], SZ_LINE, "%%%dt%s") + call pargi ((LEN_LINE - strlen (Memc[param])) / 2) + call pargstr (Memc[param]) + } else if (nscan() == 4) { + call sprintf (Memc[str], SZ_LINE, "%%%dt%s=") + call pargi (len+1) + call pargstr (Memc[param]) + call strcat (Memc[str], Memc[outstr], SZ_LINE) + + call sprintf (Memc[str], SZ_LINE, Memc[format]) + switch (Memc[type]) { + case 'b': + call pargb (apgetb (Memc[param])) + case 'i': + call pargi (apgeti (Memc[param])) + case 'r': + call pargr (apgetr (Memc[param])) + case 's': + call apgstr (Memc[param], Memc[instr], SZ_LINE) + call pargstr (Memc[instr]) + } + call strcat (Memc[str], Memc[outstr], SZ_LINE) + } + len = len + nchar + } + call strcat ("\n", Memc[outstr], SZ_LINE) + call fprintf (out, Memc[outstr]) + + call close (in) + call close (out) + call sfree (sp) +end diff --git a/noao/twodspec/apextract/appars.x b/noao/twodspec/apextract/appars.x new file mode 100644 index 00000000..8f68c0c9 --- /dev/null +++ b/noao/twodspec/apextract/appars.x @@ -0,0 +1,261 @@ +include <math/iminterp.h> + +procedure apopset (pset) + +char pset[ARB] # Pset name +pointer pp, clopset () +common /apparam/ pp + +begin + pp = clopset (pset) +end + + +procedure apcpset () + +pointer pp +common /apparam/ pp + +begin + call clcpset (pp) +end + + +procedure apgstr (param, str, maxchar) + +char param[ARB] # Parameter name +char str[ARB] # String to return +int maxchar # Maximum length of string + +pointer pp +common /apparam/ pp + +begin + call clgpset (pp, param, str, maxchar) +end + + +bool procedure apgetb (param) + +char param[ARB] # Parameter name +bool clgpsetb() +pointer pp +common /apparam/ pp + +begin + return (clgpsetb (pp, param)) +end + + +int procedure apgeti (param) + +char param[ARB] # Parameter name +int clgpseti() +pointer pp +common /apparam/ pp + +begin + return (clgpseti (pp, param)) +end + + +real procedure apgetr (param) + +char param[ARB] # Parameter name +real clgpsetr() +pointer pp +common /apparam/ pp + +begin + return (clgpsetr (pp, param)) +end + + +real procedure apgimr (param, im) + +char param[ARB] # Parameter name +pointer im # IMIO pointer +int i, ctor() +pointer pp, sp, str +real rval, imgetr() +common /apparam/ pp +errchk imgetr + +begin + call smark (sp) + call salloc (str, SZ_FNAME, TY_CHAR) + call clgpset (pp, param, Memc[str], SZ_FNAME) + i = 1 + if (ctor (Mems[str], i, rval) == 0) + rval = imgetr (im, Memc[str]) + call sfree (sp) + return (rval) +end + + +int procedure apgwrd (param, keyword, maxchar, dictionary) + +char param[ARB] # CL parameter string +char keyword[ARB] # String matched in dictionary +int maxchar # Maximum size of str +char dictionary[ARB] # Dictionary string + +int i, strdic() +pointer pp +common /apparam/ pp + +begin + call clgpset (pp, param, keyword, maxchar) + i = strdic (keyword, keyword, maxchar, dictionary) + if (i <= 0) + call error (1, "Ambiguous or unknown parameter value") + return (i) +end + + +# APGINTERP -- Select an interpolator from a CL input string. The procedure +# is coded to be protected from changes in the values of the interpolator +# types in interpdef.h. + +int procedure apginterp (param) + +char param[ARB] # CL parameter prompt string +int index, iicodes[5] +pointer sp, word +int apgwrd() +errchk apgwrd +data iicodes /II_NEAREST, II_LINEAR, II_POLY3, II_POLY5, II_SPLINE3/ + +pointer pp +common /apparam/ pp + +begin + call smark (sp) + call salloc (word, SZ_FNAME, TY_CHAR) + + index = max (1, min (5, apgwrd (param, Memc[word], SZ_FNAME, + "|nearest|linear|poly3|poly5|spline3|"))) + + call sfree (sp) + return (iicodes[index]) +end + + +procedure appstr (param, str) + +char param[ARB] # Parameter name +char str[ARB] # String to be put +pointer pp, sp, str1, str2 +common /apparam/ pp + +int i, strmatch(), stridxs() + +begin + if (strmatch (param, "p_") == 0) { + call smark (sp) + call salloc (str1, SZ_FNAME, TY_CHAR) + call salloc (str2, SZ_LINE, TY_CHAR) + call sprintf (Memc[str1], SZ_FNAME, "%s.p_prompt") + call pargstr (param) + call clgpset (pp, Memc[str1], Memc[str2], SZ_LINE) + if (Memc[str2] == '>') { + i = stridxs (" \\\t\n", Memc[str2]) + if (i > 0) + Memc[str2+i-1] = EOS + call clpstr (Memc[str2+1], str) + } else + call clppset (pp, param, str) + call sfree (sp) + } else + call clppset (pp, param, str) +end + + +procedure apputb (param, bval) + +char param[ARB] # Parameter name +bool bval # Value to be put +pointer pp, sp, str1, str2 +common /apparam/ pp + +int i, strmatch(), stridxs() + +begin + if (strmatch (param, "p_") == 0) { + call smark (sp) + call salloc (str1, SZ_FNAME, TY_CHAR) + call salloc (str2, SZ_LINE, TY_CHAR) + call sprintf (Memc[str1], SZ_FNAME, "%s.p_prompt") + call pargstr (param) + call clgpset (pp, Memc[str1], Memc[str2], SZ_LINE) + if (Memc[str2] == '>') { + i = stridxs (" \\\t\n", Memc[str2]) + if (i > 0) + Memc[str2+i-1] = EOS + call clputb (Memc[str2+1], bval) + } else + call clppsetb (pp, param, bval) + call sfree (sp) + } else + call clppsetb (pp, param, bval) +end + + +procedure apputi (param, ival) + +char param[ARB] # Parameter name +int ival # Value to be put +pointer pp, sp, str1, str2 +common /apparam/ pp + +int i, strmatch(), stridxs() + +begin + if (strmatch (param, "p_") == 0) { + call smark (sp) + call salloc (str1, SZ_FNAME, TY_CHAR) + call salloc (str2, SZ_LINE, TY_CHAR) + call sprintf (Memc[str1], SZ_FNAME, "%s.p_prompt") + call pargstr (param) + call clgpset (pp, Memc[str1], Memc[str2], SZ_LINE) + if (Memc[str2] == '>') { + i = stridxs (" \\\t\n", Memc[str2]) + if (i > 0) + Memc[str2+i-1] = EOS + call clputi (Memc[str2+1], ival) + } else + call clppseti (pp, param, ival) + call sfree (sp) + } else + call clppseti (pp, param, ival) +end + + +procedure apputr (param, rval) + +char param[ARB] # Parameter name +real rval # Value to be put +pointer pp, sp, str1, str2 +common /apparam/ pp + +int i, strmatch(), stridxs() + +begin + if (strmatch (param, "p_") == 0) { + call smark (sp) + call salloc (str1, SZ_FNAME, TY_CHAR) + call salloc (str2, SZ_LINE, TY_CHAR) + call sprintf (Memc[str1], SZ_FNAME, "%s.p_prompt") + call pargstr (param) + call clgpset (pp, Memc[str1], Memc[str2], SZ_LINE) + if (Memc[str2] == '>') { + i = stridxs (" \\\t\n", Memc[str2]) + if (i > 0) + Memc[str2+i-1] = EOS + call clputr (Memc[str2+1], rval) + } else + call clppsetr (pp, param, rval) + call sfree (sp) + } else + call clppsetr (pp, param, rval) +end diff --git a/noao/twodspec/apextract/apprint.x b/noao/twodspec/apextract/apprint.x new file mode 100644 index 00000000..b2bf17f0 --- /dev/null +++ b/noao/twodspec/apextract/apprint.x @@ -0,0 +1,34 @@ +include "apertures.h" + +# AP_PRINT -- Print the parameters of the indexed aperture. + +procedure ap_print (index, line, all, aps) + +int index # Index of aperture +int line # Dispersion line +int all # All flag +pointer aps[ARB] # Apertures + +int apaxis +pointer ap +real ap_cveval() + +begin + if (index < 1) + return + + if (all == YES) + call printf ("ALL: ") + else + call printf (" ") + + ap = aps[index] + apaxis = AP_AXIS(ap) + call printf ( +"aperture = %d beam = %d center = %.2f low = %.2f upper = %.2f\n") + call pargi (AP_ID(ap)) + call pargi (AP_BEAM(ap)) + call pargr (AP_CEN(ap, apaxis)+ap_cveval (AP_CV(ap), real (line))) + call pargr (AP_LOW(ap, apaxis)) + call pargr (AP_HIGH(ap, apaxis)) +end diff --git a/noao/twodspec/apextract/approfile.x b/noao/twodspec/apextract/approfile.x new file mode 100644 index 00000000..eeb31a6d --- /dev/null +++ b/noao/twodspec/apextract/approfile.x @@ -0,0 +1,765 @@ +include <mach.h> +include <gset.h> +include <math/curfit.h> +include "apertures.h" + + +# AP_PROFILE -- Determine spectrum profile with pixel rejection. +# +# The profile is determined by dividing each dispersion point by an estimate +# of the spectrum and then smoothing and normalizing to unit integral. +# This routine has two algorithms (procedures) for smoothing, one for nearly +# aligned spectra and one for tilted spectra. The selection is determined +# by the calling program and signaled by whether there is a variation in +# the profile offsets. For both smoothing algorithms the same iterative +# rejection algorithm may be used to eliminate deviant points from affecting +# the profile. This rejection is selected by the "clean" parameter. +# A plot of the final profile along the dispersion may be made for the +# special plotfile "debugfits" or "debugall". +# +# Dispersion points with saturated pixels are ignored as well a when the +# total sky subtracted flux is negative. + +procedure ap_profile (im, ap, dbuf, nc, nl, c1, l1, sbuf, svar, profile, nx, ny, + xs, ys, asi) + +pointer im # IMIO pointer +pointer ap # Aperture structure +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +pointer sbuf # Sky values (NULL if none) +pointer svar # Sky variances +real profile[ny,nx] # Profile (returned) +int nx, ny # Size of profile array +int xs[ny], ys # Origin of profile array +pointer asi # Image interpolator for edge pixel weighting + +real gain # Gain +real rdnoise # Readout noise +real saturation # Maximum value for an unsaturated pixel +bool clean # Clean cosmic rays? +real lsigma, usigma # Rejection sigmas. + +int fd, ix, iy, ix1, ix2, xs1, xs2, nsum +int i, niterate, ixrej, iyrej, nrej, nreject +real p, s, chisq, tfac, rrej, predict, var0, var, vmin, resid, wt1, wt2, dat +pointer sp, str, spec, x1, x2, y, reject, xreject, data, sky, cv, gp + +int apgeti() +real apgetr(), ap_cveval(), apgimr() +bool apgetb() +errchk salloc, ap_horne, ap_marsh, apgimr, ap_asifit + +begin + # Allocate memory. Adjust pointers to be one indexed. + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (spec, ny, TY_REAL) + call salloc (x1, ny, TY_REAL) + call salloc (x2, ny, TY_REAL) + call salloc (y, ny, TY_REAL) + call salloc (reject, nx*ny, TY_BOOL) + if (sbuf == NULL) { + call salloc (sky, nx, TY_REAL) + sky = sky - 1 + } + spec=spec-1; x1=x1-1; x2=x2-1; y=y-1 + + # Get task parameters. + gain = apgimr ("gain", im) + rdnoise = apgimr ("readnoise", im) ** 2 + saturation = apgetr ("saturation") + if (!IS_INDEF(saturation)) + saturation = saturation * gain + lsigma = apgetr ("lsigma") + usigma = apgetr ("usigma") + clean = apgetb ("clean") + if (clean) + niterate = apgeti ("niterate") + else + niterate = 0 + + # Initialize. + if (rdnoise == 0.) + vmin = 1. + else + vmin = rdnoise + if (sbuf == NULL) { + call aclrr (Memr[sky+1], nx) + var0 = rdnoise + } + cv = AP_CV(ap) + + # Set aperture limits and initialize rejection flags. + call alimi (xs, ny, xs1, xs2) + i = AP_AXIS(ap) + p = AP_CEN(ap,i) + AP_LOW(ap,i) + s = AP_CEN(ap,i) + AP_HIGH(ap,i) + xreject = reject + do iy = 1, ny { + dat = ap_cveval (cv, real (iy + ys - 1)) - c1 + 1 + Memr[x1+iy] = p + dat + Memr[x2+iy] = s + dat + Memr[x1+iy] = max (0.5, Memr[x1+iy]) + c1 - xs[iy] + Memr[x2+iy] = min (nc + 0.49, Memr[x2+iy]) + c1 - xs[iy] + ix1 = nint (Memr[x1+iy]) + ix2 = nint (Memr[x2+iy]) + Memr[y+iy] = iy + do ix = 1, nx { + if (ix < ix1 || ix > ix2) + Memb[xreject] = false + else + Memb[xreject] = true + xreject = xreject + 1 + } + } + + # Estimate spectrum by summing across the aperture with partial + # pixel estimates at the aperture edges. The initial profile + # estimates are obtained by normalizing by the spectrum estimate. + # Profiles where the spectrum is below sky are set to zero. + + call aclrr (profile, nx * ny) + nrej = 0 + do iy = 1, ny { + if (Memr[x1+iy] >= Memr[x2+iy]) { + Memr[spec+iy] = 0. + do ix = 1, nx + profile[iy,ix] = 0. + next + } + + call ap_asifit (dbuf+(iy+ys-1-l1)*nc, nc, xs[iy]-c1+1, + Memr[x1+iy]-c1+xs[iy], Memr[x2+iy]-c1+xs[iy], data, asi) + if (sbuf != NULL) + sky = sbuf + (iy - 1) * nx - 1 + call ap_edge (asi, Memr[x1+iy]+1, Memr[x2+iy]+1, wt1, wt2) + ix1 = nint (Memr[x1+iy]) + ix2 = nint (Memr[x2+iy]) + s = 0. + do ix = ix1, ix2 { + if (!IS_INDEF(saturation)) + if (Memr[data+ix] > saturation) { + s = 0. + nrej = nrej + 1 + break; + } + dat = Memr[data+ix] - Memr[sky+ix] + if (ix1 == ix2) + dat = wt1 * dat + else if (ix == ix1) + dat = wt1 * dat + else if (ix == ix2) + dat = wt2 * dat + s = s + dat + } + + if (s > 0.) { + do ix = ix1, ix2 + profile[iy,ix] = max (0., (Memr[data+ix]-Memr[sky+ix])/s) + } else { + do ix = ix1, ix2 + profile[iy,ix] = 0. + } + Memr[spec+iy] = s + } + + if (nrej == ny) + call error (1, "All profiles contain saturated pixels") + else if (nrej > 0) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT: %d profiles with saturated pixels in aperture %d") + call pargi (nrej) + call pargi (AP_ID(ap)) + if (nrej < ny / 3) + call ap_log (Memc[str], YES, NO, NO) + else + call ap_log (Memc[str], YES, NO, YES) + } + + # Smooth the profile and possibly reject deviant pixels. + nreject = 0 + tfac = 2. + do i = 0, niterate { + + # Estimate profile. + if (xs1 == xs2) + call ap_horne (im, cv, dbuf, nc, nl, c1, l1, Memr[spec+1], sbuf, + svar, Memb[reject], profile, nx, ny, xs, ys, + Memr[x1+1], Memr[x2+1]) + else + call ap_marsh (im, dbuf, nc, nl, c1, l1, Memr[spec+1], sbuf, + svar, Memb[reject], profile, nx, ny, xs, ys, + Memr[x1+1], Memr[x2+1]) + + if (i == niterate) + break + + # Reject pixels. The rejection threshold is based on the overall + # chi square. Pixels are rejected on the basis of the current + # chi square and the largest residual not rejected is compared + # against the final chi square to possibly trigger another round + # of rejections. + + chisq = 0.; nsum = 0; ixrej = 0; iyrej = 0; rrej = 0.; nrej = 0 + do iy = 1, ny { + s = Memr[spec+iy] + if (s <= 0.) + next + call ap_asifit (dbuf+(iy+ys-1-l1)*nc, nc, xs[iy]-c1+1, + Memr[x1+iy]-c1+xs[iy], Memr[x2+iy]-c1+xs[iy], data, asi) + if (sbuf != NULL) { + sky = sbuf + (iy - 1) * nx - 1 + var0 = rdnoise + Memr[svar+iy-1] + } + call ap_edge (asi, Memr[x1+iy]+1, Memr[x2+iy]+1, wt1, wt2) + xreject = reject + (iy - 1) * nx - 1 + ix1 = nint (Memr[x1+iy]) + ix2 = nint (Memr[x2+iy]) + do ix = ix1, ix2 { + if (Memb[xreject+ix]) { + nsum = nsum + 1 + predict = max (0., s * profile[iy,ix] + Memr[sky+ix]) + var = max (vmin, var0 + predict) + resid = (Memr[data+ix] - predict) / sqrt (var) + chisq = chisq + resid**2 + if (resid < -tfac*lsigma || resid > tfac*usigma) { + if (ix < ix1 || ix > ix2) + p = 0. + else if (ix1 == ix2) + p = wt1 + else if (ix == ix1) + p = wt1 + else if (ix == ix2) + p = wt2 + else + p = 1 + Memr[spec+iy] = Memr[spec+iy] - + p * (Memr[data+ix] - predict) + nrej = nrej + 1 + Memb[xreject+ix] = false + } else if (abs (resid) > abs (rrej)) { + rrej = resid + if (ix < ix1 || ix > ix2) + p = 0. + else if (ix1 == ix2) + p = wt1 + else if (ix == ix1) + p = wt1 + else if (ix == ix2) + p = wt2 + else + p = 1 + dat = p * (Memr[data+ix] - predict) + ixrej = ix + iyrej = iy + } + } + } + } + + if (nsum == 0) + call error (1, "All pixels rejected") + tfac = sqrt (chisq / nsum) + if (rrej < -tfac * lsigma || rrej > tfac * usigma) { + Memr[spec+iyrej] = Memr[spec+iyrej] - dat + xreject = reject + (iyrej - 1) * nx - 1 + Memb[xreject+ixrej] = false + nrej = nrej + 1 + } + + nreject = nreject + nrej + if (nrej == 0) + break + } + + # These plots are too big for production work but can be turned on + # for debugging. + + call ap_popen (gp, fd, "fits") + if (gp != NULL) { + ix1 = xs1 + ix2 = xs2 + nx - 1 + if (xs1 != xs2) { + ix1 = ix1 + 1 + ix2 = ix2 - 1 + } + do ix = ix1, ix2 { + nrej = 0 + do iy = 1, ny { + i = ix - xs[iy] + 1 + if (i < 1 || i > nx) + next + if (Memr[spec+iy] <= 0.) + next + data = dbuf + (iy + ys - 1 - l1) * nc + ix - c1 - 1 + if (sbuf != NULL) + s = Memr[sbuf+(iy-1)*nx+i-1] + else + s = Memr[sky+i] + nrej = nrej + 1 + Memr[y+nrej] = iy + ys - 1 + Memr[x1+nrej] = max (-.1, min (1.1, + (Memr[data+1] - s) / Memr[spec+iy])) + Memr[x2+nrej] = profile[iy,i] + } + call gclear (gp) + call gascale (gp, Memr[x1+1], nrej, 2) + call grscale (gp, Memr[x2+1], nrej, 2) + call gswind (gp, Memr[y+1], Memr[y+nrej], INDEF, INDEF) + if (AP_AXIS(ap) == 1) { + call sprintf (Memc[str], SZ_LINE, "Column %d") + call pargi (ix) + call glabax (gp, Memc[str], "Line", "Profile") + } else { + call sprintf (Memc[str], SZ_LINE, "Line %d") + call pargi (ix) + call glabax (gp, Memc[str], "Column", "Profile") + } + call gpmark (gp, Memr[y+1], Memr[x1+1], nrej, GM_POINT, 1., 1.) + call gpline (gp, Memr[y+1], Memr[x2+1], nrej) + } + } + call ap_pclose (gp, fd) + + # Log the number of rejected pixels. + if (clean) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT: %d pixels rejected for profile from aperture %d") + call pargi (nreject) + call pargi (AP_ID(ap)) + call ap_log (Memc[str], YES, NO, NO) + } + + call sfree (sp) +end + + +# AP_HORNE -- Determine profile by fitting a low order function parallel to +# dispersion along image lines or columns after dividing by a spectrum +# estimate. An initial profile estimate and a rejection array are +# required for setting the weights. This is a straightforward algorithm +# similar to images.fit1d except that it is noninteractive. The fitting +# function is fixed at a cubic spline and the number of pieces is set by +# the amount of tilt such that there is one cubic spline piece per +# passage across the tilted spectrum plus an amount based on the order +# of the tracing function. It is named after Keith Horne +# since this is what is outlined in his paper. The profile array is used +# cleverly to minimize memory requirements. The storage order of the +# profile array, which is transposed relative to the data, is determined +# by this procedure. + +procedure ap_horne (im, cvtrace, dbuf, nc, nl, c1, l1, spec, sbuf, svar, reject, + profile, nx, ny, xs, ys, x1, x2) + +pointer im # IMIO pointer +pointer cvtrace # Trace pointer +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real spec[ny] # Spectrum estimate +pointer sbuf # Sky values (NULL if none) +pointer svar # Sky variances +bool reject[nx,ny] # Rejection flags +real profile[ny,nx] # Initial profile in, improved profile out +int nx, ny # Size of profile array +int xs[ny], ys # Origin of profile array +real x1[ny], x2[ny] # Aperture limits in profile array + +int cvtype # Curfit type +int order # Order of curfit function. +real rdnoise # Readout noise in RMS data numbers. + +int ix, iy, ierr +real p, s, sk, var, vmin, var0, wmin +pointer sp, y, w, cv, dbuf1, data, sky + +#int apgeti() +int cvstati() +real apgimr() +errchk salloc, apgimr + +begin + call smark (sp) + call salloc (y, ny, TY_REAL) + call salloc (w, ny, TY_REAL) + + # Get CL parameters + #cvtype = apgeti ("e_function") + #order = apgeti ("e_order") + rdnoise = apgimr ("readnoise", im) ** 2 + + # Initialize. + call alimr (x1, ny, p, s) + cvtype = SPLINE3 + order = int (s - p + 1) + max (0, cvstati (cvtrace, CVNCOEFF) - 2) + #order = min (20, order) + order = 2 * order + call cvinit (cv, cvtype, order, 1., real (ny)) + do iy = 1, ny + Memr[y+iy-1] = iy + if (rdnoise == 0.) + vmin = 1. + else + vmin = rdnoise + dbuf1 = dbuf + (ys - l1 - 1) * nc - c1 - 1 + if (sbuf == NULL) { + sk = 0. + var0 = rdnoise + } + + # For each line parallel to the dispersion divide by a spectrum + # estimate and then fit the smoothing function. Use the input + # profile and rejection array to set the weights. + + do ix = 1, nx { + data = dbuf1 + ix + if (sbuf != NULL) + sky = sbuf - nx - 1 + ix + wmin = MAX_REAL + do iy = 1, ny { + s = spec[iy] + if (s > 0. && reject[ix,iy]) { + if (sbuf != NULL) { + sk = Memr[sky+iy*nx] + var0 = rdnoise + Memr[svar+iy-1] + } + p = profile[iy,ix] + var = max (vmin, var0 + max (0., s * p + sk)) + var = (s ** 2) / var + wmin = min (wmin, var) + Memr[w+iy-1] = var + profile[iy,ix] = (Memr[data+iy*nc+xs[iy]] - sk) / s + } else + Memr[w+iy-1] = 0. + } + if (wmin == MAX_REAL) + call amovkr (1., Memr[w], ny) + else + call amaxkr (Memr[w], wmin / 10., Memr[w], ny) + call cvfit (cv, Memr[y], profile[1,ix], Memr[w], ny, WTS_USER, ierr) + call cvvector (cv, Memr[y], profile[1,ix], ny) + call amaxkr (profile[1,ix], 0., profile[1,ix], ny) + } + + call cvfree (cv) + call sfree (sp) +end + + +# AP_MARSH -- Determine profile by Marsh algorithm (PASP V101, P1032, 1989). +# This algorithm fits low order polynomials to weighted points sampled +# at uniform intervals parallel to the aperture trace. The polynomials +# are coupled through the weights and so requires a 2D matrix inversion. +# This is a relatively slow algorithm but does provide low order smoothing +# for arbitrary profile shapes in highly tilted spectra. An estimate +# of the profile, a rejection array, sky and sky variance, and aperture +# limit arrays are required. + +procedure ap_marsh (im, dbuf, nc, nl, c1, l1, spec, sbuf, svar, reject, + profile, nx, ny, xs, ys, x1, x2) + +pointer im # IMIO pointer +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real spec[ny] # Spectrum estimate +pointer sbuf # Sky values (NULL if none) +pointer svar # Sky variances +bool reject[nx,ny] # Rejection flags +real profile[ny,nx] # Initial profile in, improved profile out +int nx, ny # Size of profile array +int xs[ny], ys # Origin of profile array +real x1[ny], x2[ny] # Aperture limits in profile array + +real spix # Polynomial pixel separation +int npols # Number of polynomials +int order # Order of function. +real rdnoise # Readout noise in RMS data numbers. + +int il, jl, kl, ll, ix, iy, ix1, ix2, nside, nadd +int ip, ip1, ip2, index1, index2, index3 +real p, s, s2, dat, sk, var, vmin, var0 +real dx0, dx1, dx2, dx3, dx4, xj, xk, xt, xz, qj, qk, xadd +double sum1, sum2 +pointer sp, work, work1, work2, work3, work4, ysum, data, sky + +int apgeti() +real apgetr(), apgimr() +errchk salloc, apgimr + +begin + # Get CL parameters + #npols = apgeti ("npols") + spix = apgetr ("polysep") + order = apgeti ("polyorder") + rdnoise = apgimr ("readnoise", im) ** 2 + + # Set dimensions. + npols = (x2[1] - x1[1] + 2) / spix + spix = (x2[1] - x1[1] + 2) / real (npols) + nside = npols * order + nadd = nside * nside + if (spix > 1.) + call error (4, "Polynomial separation too large") + + # Allocate memory. One index pointers. + call smark (sp) + call salloc (work, nadd+3*nside, TY_REAL) + call salloc (work4, nside, TY_INT) + call salloc (ysum, ny, TY_REAL) + work = work - 1 + work1 = work + nadd + work2 = work1 + nside + work3 = work2 + nside + work4 = work4 - 1 + ysum=ysum-1 + if (sbuf == NULL) { + call salloc (sky, nx, TY_REAL) + sky = sky - 1 + } + + # Initialize. + call aclrr (Memr[work+1], nadd+3*nside) + call aclri (Memi[work4+1], nside) + if (rdnoise == 0.) + vmin = 1. + else + vmin = rdnoise + if (sbuf == NULL) { + call aclrr (Memr[sky+1], nx) + var0 = rdnoise + } + + # Factors for weights. + dx0 = 0.5 - spix + dx1 = abs (dx0) + dx2 = 1. - (dx0 / spix) ** 2 + dx3 = 0.5 + spix + dx4 = sqrt (2.) * spix + + # Accumulate least terms for least squares matrix equation AX = B. + + # First accumulate B. + do jl = 0, npols-1 { + do iy = 1, ny { + if (spec[iy] <= 0.) + next + + xj = x1[iy] - 1 + spix * (real (jl) + 0.5) + ix1 = nint (xj - spix) + ix2 = nint (xj + spix) + if (ix1 < 1 || ix2 > nx) { + Memr[ysum+iy] = 0. + next + } + + data = dbuf + (iy + ys - 1 - l1) * nc + xs[iy] - c1 - 1 + if (sbuf != NULL) { + sky = sbuf + (iy - 1) * nx - 1 + var0 = rdnoise + Memr[svar+iy-1] + } + + # Evaluate qj, the contribution of polynomial number jl+1 + # for the pixel ix1,jj. Four cases are considered. The + # first two account for the triangular interpolation + # function partially overlapping a pixel, on one side + # only. The third is for the function wholly inside a + # pixel, and finally for the pixel wholly covered by the + # interpolation function. + + s = spec[iy] + sum1 = 0. + do ix = ix1, ix2 { + if (!reject[ix,iy]) + next + p = profile[iy,ix] + sk = Memr[sky+ix] + dat = Memr[data+ix] - sk + var = max (vmin, var0 + max (0., s * p + sk)) + + xz = xj - real (ix) + xt = abs (xz) + if (xt >= dx1) { + if (xt >= 0.5) + qj = ((xt - dx3) / dx4) ** 2 + else + qj = 1.- ((xt - dx0) / dx4) ** 2 + + } else if (xt <= dx0) + qj = 1. + else + qj = dx2 - (xz / spix) ** 2 + sum1 = sum1 + qj * s * dat / var + } + Memr[ysum+iy] = sum1 + } + + index1 = order * jl + do il = 1, order { + sum1 = 0. + ip = il - 1 + do iy = 1, ny + if (spec[iy] > 0.) + sum1 = sum1 + Memr[ysum+iy] * ((real (iy) / ny) ** ip) + Memr[work1+index1+il] = sum1 + } + } + + # Now accumulate matrix A. Since it is symmetric we only need to + # evaluate half of it. Since it is banded we only need to evaluate + # contribution if two polynomial terms can be affected by the same + # pixel. + + ip1 = nside - 1 + ip2 = order * ip1 + do jl = 0, npols-1 { + do kl = 0, jl { + if (spix * (jl - kl - 2) > 0.) + next + do iy = 1, ny { + if (spec[iy] <= 0.) + next + if (sbuf != NULL) { + sky = sbuf + (iy - 1) * nx - 1 + var0 = rdnoise + Memr[svar+iy-1] + } + + # Compute left and right limits of polynomials jl+1 + # and kl+1 for this value of y Evaluate sum over row + # of qj[jl+1] times qj[kl+1] where qj[i] is fraction + # of polynomial i which contributes to to pixel ix,jj. + + xj = x1[iy] - 1 + spix * (real (jl) + 0.5) + xk = x1[iy] - 1 + spix * (real (kl) + 0.5) + ix1 = nint (xj - spix) + ix2 = nint (xk + spix) + + if (ix2 < ix1 || ix1 < 1 || ix2 > nx) { + Memr[ysum+iy] = 0. + next + } + + s = spec[iy] + s2 = s * s + sum1 = 0. + do ix = ix1, ix2 { + if (reject[ix,iy]) { + p = profile[iy,ix] + sk = Memr[sky+ix] + var = max (vmin, var0 + max (0., s * p + sk)) + + xz = xj - real (ix) + xt = abs (xz) + if (xt >= dx1) { + if (xt >= 0.5) + qj = ((xt-dx3)/dx4)**2 + else + qj = 1.- ((xt-dx0)/dx4)**2 + } else if (xt <= dx0) + qj = 1. + else + qj = dx2 - (xz / spix) ** 2 + if (kl != jl) { + xz = xk - real (ix) + xt = abs (xz) + if (xt >= dx1) { + if (xt >= 0.5) + qk = ((xt-dx3)/dx4)**2 + else + qk = 1.-((xt-dx0)/dx4)**2 + } else if (xt <= dx0) + qk = 1. + else + qk = dx2 - (xz / spix) ** 2 + } else + qk = qj + sum1 = sum1 + qj * qk * s2 / var + } + } + Memr[ysum+iy] = sum1 + } + + do il = 1, order { + do ll = 1, il { + sum1 = 0. + ip = il + ll - 2 + do iy = 1, ny + if (spec[iy] > 0.) + sum1 = sum1 + + Memr[ysum+iy] * ((real (iy) / ny)**ip) + index1 = nside * (order*jl+il-1) + order * kl + ll + Memr[work+index1] = sum1 + if (ll != il) { + ip = ip1 * (ll - il) + index2 = index1 + ip + Memr[work+index2] = sum1 + } else + index2 = index1 + if (kl != jl) { + index3 = index2 + ip2 * (kl - jl) + Memr[work+index3] = sum1 + if (ll != il) + Memr[work+index3-ip] = sum1 + } + } + } + } + } + + # Solve matrix equation AX = B for X. A is a real symmetric, + # positive definite matrix, dimension (order*npols)**2. X is + # the vector representing the coefficients fitted to the + # normalized profile. Coefficients are reordered for later speed. + + call hfti (Memr[work+1], nside, nside, nside, Memr[work1+1], 1, 1, + 0.01, ip, p, Memr[work2+1], Memr[work3+1], Memi[work4+1]) + + do jl = 1, order { + do il = 1, npols { + index1 = order * (il - 1) + jl + index2 = npols * (jl - 1) + il + Memr[work+index2] = Memr[work1+index1] + } + } + + # Evaluate fit and make profile positive only. + do iy = 1, ny { + ix1 = nint (x1[iy]) + ix2 = nint (x2[iy]) + xadd = x1[iy] - 1 + s = 0. + do ix = 1, nx { + xj = real (ix) - xadd - 0.5 + xk = real (ix) - xadd + 0.5 + ip1 = int (xj / spix + 0.5) + ip2 = int (xk / spix + 1.5) + ip1 = max (1, min (ip1, npols)) + ip2 = max (1, min (ip2, npols)) + sum1 = 0. + do jl = 0, order-1 { + index1 = npols * jl + sum2 = 0. + do il = ip1, ip2 { + xz = xadd + spix * (real (il-1) + 0.5) - real (ix) + xt = abs (xz) + if (xt >= dx1) { + if (xt >= 0.5) + qj = ((xt - dx3) / dx4) ** 2 + else + qj = 1. - ((xt - dx0) / dx4) ** 2 + } else if (xt <= dx0) + qj = 1. + else + qj = dx2 - (xz / spix) ** 2 + sum2 = sum2 + qj * Memr[work+index1+il] + } + sum1 = sum1 + sum2 * ((real (iy)/ ny) ** jl) + } + profile[iy,ix] = max (0.d0, sum1) + } + } + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/aprecenter.par b/noao/twodspec/apextract/aprecenter.par new file mode 100644 index 00000000..a76b4c76 --- /dev/null +++ b/noao/twodspec/apextract/aprecenter.par @@ -0,0 +1,17 @@ +# APRECENTER + +input,s,a,,,,List of input images +apertures,s,h,"",,,Apertures +references,s,h,"",,,"Reference images +" +interactive,b,h,no,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,yes,,,Recenter apertures? +resize,b,h,no,,,Resize apertures? +edit,b,h,yes,,,"Edit apertures? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,1,,,Number of dispersion lines to sum or median +aprecenter,s,h,"",,,Apertures for recentering calculation +npeaks,r,h,INDEF,0.,,Select brightest peaks +shift,b,h,yes,,,Use average shift instead of recentering? diff --git a/noao/twodspec/apextract/aprecenter.x b/noao/twodspec/apextract/aprecenter.x new file mode 100644 index 00000000..fb3b9a86 --- /dev/null +++ b/noao/twodspec/apextract/aprecenter.x @@ -0,0 +1,166 @@ +include "apertures.h" + +define NRANGES 50 + +# AP_RECENTER -- Recenter apertures. + +procedure ap_recenter (image, line, nsum, aps, naps, apedit) + +char image[SZ_FNAME] # Image name +int line # Image dispersion line +int nsum # Number of dispersion lines to sum +pointer aps[ARB] # Aperture pointers +int naps # Number of apertures +int apedit # Called by apedit? + +pointer ranges # Apertures to select +int npeaks # Number of bright peaks to select +bool shift # Shift instead of center? + +real center, delta +int i, j, k, na, npts, apaxis +pointer sp, str, im, imdata, title, index, peaks, deltas + +int decode_ranges() +real apgetr(), ap_center(), ap_cveval(), asokr() +bool clgetb(), ap_answer(), apgetb(), is_in_range() +errchk ap_getdata + +begin + # Check if apertures are defined. + na = 0 + do i = 1, naps + if (AP_SELECT(aps[i]) == YES) + na = na + 1 + if (na < 1) + return + + # Query user. + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + if (apedit == NO) { + call sprintf (Memc[str], SZ_LINE, "Recenter apertures for %s?") + call pargstr (image) + if (!ap_answer ("ansrecenter", Memc[str])) { + call sfree (sp) + return + } + + if (clgetb ("verbose")) + call printf ("Recentering apertures ...\n") + } + + # Get parameters + delta = apgetr ("npeaks") + shift = apgetb ("shift") + if (IS_INDEFR (delta)) + npeaks = naps + else if (delta < 1.) + npeaks = max (1., delta * naps) + else + npeaks = delta + + # Map the image and get the image data. + call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, title) + + if (npeaks == naps && !shift) { + na = 0 + do i = 1, naps { + if (AP_SELECT(aps[i]) == NO) + next + center = AP_CEN(aps[i], apaxis) + + ap_cveval (AP_CV(aps[i]), real (line)) + center = ap_center (center, Memr[imdata], npts) + if (!IS_INDEF(center)) { + AP_CEN(aps[i], apaxis) = center - + ap_cveval (AP_CV(aps[i]), real (line)) + na = na + 1 + } + } + } else { + call salloc (ranges, 3*NRANGES, TY_INT) + call salloc (index, naps, TY_REAL) + call salloc (peaks, naps, TY_REAL) + call salloc (deltas, naps, TY_REAL) + + call apgstr ("aprecenter", Memc[str], SZ_LINE) + if (decode_ranges (Memc[str], Memi[ranges], NRANGES, i) == ERR) + call error (0, "Bad aperture list") + + j = 0 + do i = 1, naps { + if (!is_in_range (Memi[ranges], AP_ID(aps[i]))) + next + center = AP_CEN(aps[i], apaxis) + + ap_cveval (AP_CV(aps[i]), real (line)) + delta = ap_center (center, Memr[imdata], npts) + if (!IS_INDEF(delta)) { + k = max (1, min (npts, int (delta+0.5))) + Memr[index+j] = i + Memr[peaks+j] = -Memr[imdata+k-1] + Memr[deltas+j] = delta - center + j = j + 1 + } + } + + if (j > 0 && npeaks > 0) { + if (npeaks < j) { + call xt_sort3 (Memr[peaks], Memr[deltas], Memr[index], j) + j = npeaks + } + + if (shift) { + if (mod (j, 2) == 0) + delta = (asokr (Memr[deltas], j, j/2) + + asokr (Memr[deltas], j, 1+j/2)) / 2 + else + delta = asokr (Memr[deltas], j, 1+j/2) + na = 0 + do i = 1, naps { + if (AP_SELECT(aps[i]) == NO) + next + center = AP_CEN(aps[i], apaxis) + delta + AP_CEN(aps[i], apaxis) = center + na = na + 1 + } + } else { + na = 0 + do k = 1, j { + delta = Memr[deltas+k-1] + i = Memr[index+k-1] + if (AP_SELECT(aps[i]) == NO) + next + center = AP_CEN(aps[i], apaxis) + delta + AP_CEN(aps[i], apaxis) = center + na = na + 1 + } + } + } + } + + # Log the operation, write the apertures to the database, + # unmap the image and free memory. + if (shift) { + call sprintf (Memc[str], SZ_LINE, + "RECENTER - %d apertures shifted by %.2f for %s.") + call pargi (na) + call pargr (delta) + call pargstr (image) + } else { + call sprintf (Memc[str], SZ_LINE, + "RECENTER - %d apertures recentered for %s") + call pargi (na) + call pargstr (image) + } + if (apedit == NO) + call ap_log (Memc[str], YES, YES, NO) + else + call ap_log (Memc[str], YES, NO, NO) + + call appstr ("ansdbwrite1", "yes") + + call mfree (imdata, TY_REAL) + call mfree (title, TY_CHAR) + call imunmap (im) + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apresize.par b/noao/twodspec/apextract/apresize.par new file mode 100644 index 00000000..4cbcf4b7 --- /dev/null +++ b/noao/twodspec/apextract/apresize.par @@ -0,0 +1,21 @@ +# APRESIZE + +input,s,a,,,,List of input images +apertures,s,h,"",,,Apertures +references,s,h,"",,,"Reference images +" +interactive,b,h,no,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,no,,,Recenter apertures? +resize,b,h,yes,,,Resize apertures? +edit,b,h,yes,,,"Edit apertures? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,1,,,Number of dispersion lines to sum or median +llimit,r,h,INDEF,,,Lower aperture limit relative to center +ulimit,r,h,INDEF,,,Upper aperture limit relative to center +ylevel,r,h,0.1,,,Fraction of peak or intensity for automatic width +peak,b,h,yes,,,Is ylevel a fraction of the peak? +bkg,b,h,yes,,,Subtract background in automatic width? +r_grow,r,h,0.,,,"Grow limits by this factor" +avglimits,b,h,no,,,Average limits over all apertures? diff --git a/noao/twodspec/apextract/apresize.x b/noao/twodspec/apextract/apresize.x new file mode 100644 index 00000000..8443223a --- /dev/null +++ b/noao/twodspec/apextract/apresize.x @@ -0,0 +1,142 @@ +include "apertures.h" + +# AP_RESIZE -- Resize apertures. + +procedure ap_resize (image, line, nsum, aps, naps, apedit) + +char image[SZ_FNAME] # Image name +int line # Image dispersion line +int nsum # Number of dispersion lines to sum +int apedit # Called from apedit? + +pointer aps[ARB] # Aperture pointers +int naps # Number of apertures + +real llimit, ulimit # Maximum aperture limits +real ylevel # Fraction of intensity for resize +bool peak # Is ylevel a fraction of the peak? +bool bkg # Subtract background? +real grow # Expand limits by this factor +bool avglimits # Average limits? + +real center, low, high +int i, na, npts, apaxis +pointer sp, str, im, imdata, title + +bool clgetb(), ap_answer(), apgetb() +real apgetr(), ap_cveval() +errchk ap_getdata + +begin + # Check if apertures are defined. + na = 0 + do i = 1, naps + if (AP_SELECT(aps[i]) == YES) + na = na + 1 + if (na == 0) + return + + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + if (apedit == NO) { + call sprintf (Memc[str], SZ_LINE, "Resize apertures for %s?") + call pargstr (image) + if (!ap_answer ("ansresize", Memc[str])) { + call sfree (sp) + return + } + + if (clgetb ("verbose")) + call printf ("Resizing apertures ...\n") + } + + # Map the image and get the image data. + call ap_getdata (image, line, nsum, im, imdata, npts, apaxis, title) + + # Resize the apertures. + llimit = apgetr ("llimit") + ulimit = apgetr ("ulimit") + ylevel = apgetr ("ylevel") + bkg = apgetb ("bkg") + peak = apgetb ("peak") + grow = apgetr ("r_grow") + avglimits = apgetb ("avglimits") + + if (IS_INDEF(llimit)) + llimit = -npts + if (IS_INDEF(ulimit)) + ulimit = npts + + high = max (llimit, ulimit) + llimit = min (llimit, ulimit) + ulimit = high + + if (IS_INDEF (ylevel)) { + do i = 1, naps { + if (AP_SELECT(aps[i]) == YES) { + AP_LOW(aps[i], apaxis) = llimit + AP_HIGH(aps[i], apaxis) = ulimit + } + } + avglimits = true + } else { + do i = 1, naps { + if (AP_SELECT(aps[i]) == YES) { + low = llimit + high = ulimit + center = AP_CEN(aps[i], apaxis) + + ap_cveval (AP_CV(aps[i]), real (line)) + call ap_ylevel (Memr[imdata], npts, ylevel, peak, bkg, grow, + center, low, high) + AP_LOW(aps[i], apaxis) = min (low, high) + AP_HIGH(aps[i], apaxis) = max (low, high) + } + } + + if (avglimits) { + low = 0. + high = 0. + do i = 1, naps { + if (AP_SELECT(aps[i]) == YES) { + low = low + AP_LOW(aps[i], apaxis) + high = high + AP_HIGH(aps[i], apaxis) + } + } + low = low / na + high = high / na + do i = 1, naps { + if (AP_SELECT(aps[i]) == YES) { + AP_LOW(aps[i], apaxis) = low + AP_HIGH(aps[i], apaxis) = high + } + } + } + } + + # Log the operation, write the apertures to the database, + # unmap the image and free memory. + if (na == 1 || avglimits) { + call sprintf (Memc[str], SZ_LINE, + "APRESIZE - %d apertures resized for %s (%.2f, %.2f)") + call pargi (na) + call pargstr (image) + call pargr (AP_LOW(aps[1], apaxis)) + call pargr (AP_HIGH(aps[1], apaxis)) + } else { + call sprintf (Memc[str], SZ_LINE, + "RESIZE - %d apertures resized for %s") + call pargi (na) + call pargstr (image) + } + if (apedit == NO) + call ap_log (Memc[str], YES, YES, NO) + else + call ap_log (Memc[str], YES, NO, NO) + + call appstr ("ansdbwrite1", "yes") + + call mfree (imdata, TY_REAL) + call mfree (title, TY_CHAR) + call imunmap (im) + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apscat1.par b/noao/twodspec/apextract/apscat1.par new file mode 100644 index 00000000..8cb5cf7b --- /dev/null +++ b/noao/twodspec/apextract/apscat1.par @@ -0,0 +1,11 @@ +# APSCAT1 + +apertures,s,h,)apscatter.apertures,,,>apall.apertures +function,s,h,"spline3","spline3|legendre|chebyshev|spline1",,Fitting function +order,i,h,1,1,,Order of fitting function +sample,s,h,"*",,,Sample points to use in fit +naverage,i,h,1,,,Number of points in sample averaging +low_reject,r,h,5.,0.,,Low rejection in sigma of fit +high_reject,r,h,2.,0.,,High rejection in sigma of fit +niterate,i,h,5,0,,Number of rejection iterations +grow,r,h,0.,0.,,Rejection growing radius in pixels diff --git a/noao/twodspec/apextract/apscat2.par b/noao/twodspec/apextract/apscat2.par new file mode 100644 index 00000000..2463f110 --- /dev/null +++ b/noao/twodspec/apextract/apscat2.par @@ -0,0 +1,10 @@ +# APSCAT2 + +function,s,h,"spline3","spline3|legendre|chebyshev|spline1",,Fitting function +order,i,h,1,1,,Order of fitting function +sample,s,h,"*",,,Sample points to use in fit +naverage,i,h,1,,,Number of points in sample averaging +low_reject,r,h,3.,0.,,Low rejection in sigma of fit +high_reject,r,h,3.,0.,,High rejection in sigma of fit +niterate,i,h,0,0,,Number of rejection iterations +grow,r,h,0.,0.,,Rejection growing radius in pixels diff --git a/noao/twodspec/apextract/apscatter.par b/noao/twodspec/apextract/apscatter.par new file mode 100644 index 00000000..b7f45991 --- /dev/null +++ b/noao/twodspec/apextract/apscatter.par @@ -0,0 +1,25 @@ +# APSCATTER + +input,s,a,,,,List of input images to subtract scattered light +output,s,a,,,,List of output corrected images +apertures,s,h,"",,,Apertures +scatter,s,h,"",,,List of scattered light images (optional) +references,s,h,"",,,"List of aperture reference images +" +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,yes,,,Recenter apertures? +resize,b,h,yes,,,Resize apertures? +edit,b,h,yes,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,Fit the traced points interactively? +subtract,b,h,yes,,,Subtract scattered light? +smooth,b,h,yes,,,Smooth scattered light along the dispersion? +fitscatter,b,h,yes,,,Fit scattered light interactively? +fitsmooth,b,h,yes,,,"Smooth the scattered light interactively? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,10,,,Number of dispersion lines to sum or median +buffer,r,h,1.,0.,,Buffer distance from apertures +apscat1,pset,h,"",,,Fitting parameters across the dispersion +apscat2,pset,h,"",,,Fitting parameters along the dispersion diff --git a/noao/twodspec/apextract/apscatter.x b/noao/twodspec/apextract/apscatter.x new file mode 100644 index 00000000..44f56a72 --- /dev/null +++ b/noao/twodspec/apextract/apscatter.x @@ -0,0 +1,662 @@ +include <error.h> +include <imhdr.h> +include <imset.h> +include <pkg/gtools.h> +include "apertures.h" + +define MAXBUF 500000 # Buffer size (number of reals) for col access + + +# AP_SCATTER -- Fit and subtract the scattered light from between the apertures. +# +# Each line of the input image across the dispersion is read. The points to +# be fit are selected from between the apertures (which includes a buffer +# distance). The fitting is done using the ICFIT package. If not smoothing +# along the dispersion write the scattered light subtracted output directly +# thus minimizing I/O. If smoothing save the fits in memory. During the +# smoothing process the fits are evaluated at each point along the dispersion +# and then fit to the create the scattered light subtracted output image. A +# scattered light image is only created after the output image by subtracting +# the input from the output. + +procedure ap_scatter (input, output, scatter, aps, naps, line) + +char input[SZ_FNAME] # Input image +char output[SZ_FNAME] # Output image +char scatter[SZ_FNAME] # Scattered light image +pointer aps[ARB] # Apertures +int naps # Number of apertures +int line # Line to be edited + +bool smooth +int i, aaxis, daxis, npts, nlines, nscatter, nscatter1, new +pointer sp, str, in, out, scat, cv, cvs, gp, indata, outdata, col, x, y, w +pointer ic1, ic2, ic3, gt1, gt2 +data ic3/NULL/ + +real clgetr() +int clgeti(), ap_gline(), ap_gdata() +bool clgetb(), ap_answer(), apgansb() +pointer gt_init(), immap(), ap_immap(), imgl2r(), impl2r() + +common /aps_com/ ic1, ic2, gt1, gt2 + +begin + if (naps < 1) + return + + # Query the user. + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call sprintf (Memc[str], SZ_LINE, "Subtract scattered light in %s?") + call pargstr (input) + if (!ap_answer ("ansscat", Memc[str])) { + call sfree (sp) + return + } + + call sprintf (Memc[str], SZ_LINE, + "Fit scattered light for %s interactively?") + call pargstr (input) + if (ap_answer ("ansfitscatter", Memc[str])) + ; + + call sprintf (Memc[str], SZ_LINE, "Smooth the scattered light in %s?") + call pargstr (input) + if (ap_answer ("anssmooth", Memc[str])) { + call sprintf (Memc[str], SZ_LINE, + "Smooth the scattered light for %s interactively?") + call pargstr (input) + if (ap_answer ("ansfitsmooth", Memc[str])) + ; + } + smooth = apgansb ("anssmooth") + + # Initialize the ICFIT pointers. + if (ic1 == NULL || ic3 == NULL) { + call ic_open (ic1) + call clgstr ("apscat1.function", Memc[str], SZ_LINE) + call ic_pstr (ic1, "function", Memc[str]) + call ic_puti (ic1, "order", clgeti ("apscat1.order")) + call clgstr ("apscat1.sample", Memc[str], SZ_LINE) + call ic_pstr (ic1, "sample", Memc[str]) + call ic_puti (ic1, "naverage", clgeti ("apscat1.naverage")) + call ic_puti (ic1, "niterate", clgeti ("apscat1.niterate")) + call ic_putr (ic1, "low", clgetr ("apscat1.low_reject")) + call ic_putr (ic1, "high", clgetr ("apscat1.high_reject")) + call ic_putr (ic1, "grow", clgetr ("apscat1.grow")) + call ic_pstr (ic1, "ylabel", "") + gt1 = gt_init() + call gt_sets (gt1, GTTYPE, "line") + + call ic_open (ic2) + call clgstr ("apscat2.function", Memc[str], SZ_LINE) + call ic_pstr (ic2, "function", Memc[str]) + call ic_puti (ic2, "order", clgeti ("apscat2.order")) + call clgstr ("apscat2.sample", Memc[str], SZ_LINE) + call ic_pstr (ic2, "sample", Memc[str]) + call ic_puti (ic2, "naverage", clgeti ("apscat2.naverage")) + call ic_puti (ic2, "niterate", clgeti ("apscat2.niterate")) + call ic_putr (ic2, "low", clgetr ("apscat2.low_reject")) + call ic_putr (ic2, "high", clgetr ("apscat2.high_reject")) + call ic_putr (ic2, "grow", clgetr ("apscat2.grow")) + call ic_pstr (ic2, "ylabel", "") + gt2 = gt_init() + call gt_sets (gt2, GTTYPE, "line") + + ic3 = ic1 + } + + # Map the input and output images. Warn and return on an error. + iferr (in = ap_immap (input, aaxis, daxis)) { + call sfree (sp) + call erract (EA_WARN) + return + } + iferr (out = immap (output, NEW_COPY, in)) { + call imunmap (in) + call sfree (sp) + call erract (EA_WARN) + return + } + if (IM_PIXTYPE(out) != TY_DOUBLE) + IM_PIXTYPE(out) = TY_REAL + + # Allocate memory for curve fitting. + call ap_sort (i, aps, naps, 1) + npts = IM_LEN (in, aaxis) + nlines = IM_LEN (in, daxis) + call salloc (col, npts, TY_REAL) + call salloc (x, npts, TY_REAL) + call salloc (y, npts, TY_REAL) + call salloc (w, npts, TY_REAL) + + do i = 1, npts + Memr[col+i-1] = i + call ic_putr (ic1, "xmin", Memr[col]) + call ic_putr (ic1, "xmax", Memr[col+npts-1]) + + # If the interactive flag is set then use icg_fit to set the + # fitting parameters. AP_GLINE returns EOF when the user + # is done. + + if (apgansb ("ansfitscatter")) { + call ap_gopen (gp) + + if (IS_INDEFI (line)) + i = nlines / 2 + else + i = line + indata = NULL + while (ap_gline (ic1, gt1, NULL, in, aaxis, aaxis, i, indata) != + EOF) { + call ap_gscatter1 (aps, naps, i, Memr[indata], npts, + Memr[x], Memr[y], Memr[w], nscatter) + call icg_fit (ic1, gp, "gcur", gt1, cv, Memr[x], Memr[y], + Memr[w], nscatter) + } + call cvfree (cv) + } + + # Loop through the input image and create an output image. + # To minimize I/O if not smoothing write the final image + # directly otherwise save the fit. AP_SMOOTH will then + # smooth along the dispersion and compute the scattered + # light subtracted image. + + if (clgetb ("verbose")) { + call printf ( + "Fitting the scattered light across the dispersion ...\n") + call flush (STDOUT) + } + + if (!smooth) { + nscatter = 0 + i = 0 + while (ap_gdata (in, out, NULL, aaxis, MAXBUF, i, + indata, outdata) != EOF) { + call ap_gscatter1 (aps, naps, i, Memr[indata], npts, Memr[x], + Memr[y], Memr[w], nscatter1) + if (nscatter != nscatter1) + new = YES + else + new = NO + nscatter = nscatter1 + call ic_fit (ic1, cv, Memr[x], Memr[y], Memr[w], nscatter, + new, YES, new, new) + call cvvector (cv, Memr[col], Memr[outdata], npts) + call asubr (Memr[indata], Memr[outdata], Memr[outdata], npts) + } + call cvfree (cv) + } else { + call salloc (cvs, nlines, TY_POINTER) + call amovki (NULL, Memi[cvs], nlines) + + new = YES + i = 0 + while (ap_gdata (in, NULL, NULL, aaxis, MAXBUF, i, + indata, outdata) != EOF) { + call ap_gscatter1 (aps, naps, i, Memr[indata], npts, Memr[x], + Memr[y], Memr[w], nscatter) + call ic_fit (ic1, Memi[cvs+i-1], Memr[x], Memr[y], Memr[w], + nscatter, new, YES, new, new) + } + + # Smooth and subtract along the dispersion. + call ap_smooth (in, out, aaxis, daxis, aps, naps, ic2, gt2, cvs) + do i = 1, nlines + call cvfree (Memi[cvs+i-1]) + } + + call imastr (out, "apscatter", "Scattered light subtracted") + call imunmap (out) + call imunmap (in) + + # If a scattered light image is desired compute it from the difference + # of the input and output images. + + if (scatter[1] != EOS) { + in = immap (input, READ_ONLY, 0) + out = immap (output, READ_ONLY, 0) + ifnoerr (scat = immap (scatter, NEW_COPY, in)) { + if (IM_PIXTYPE(scat) != TY_DOUBLE) + IM_PIXTYPE(scat) = TY_REAL + npts = IM_LEN(in,1) + nlines = IM_LEN(in,2) + do i = 1, nlines + call asubr (Memr[imgl2r(in,i)], Memr[imgl2r(out,i)], + Memr[impl2r(scat,i)], npts) + call imunmap (scat) + } else + call erract (EA_WARN) + call imunmap (in) + call imunmap (out) + } + + # Make a log. + call sprintf (Memc[str], SZ_LINE, + "SCATTER - Scattered light subtracted from %s") + call pargstr (input) + call ap_log (Memc[str], YES, YES, NO) + + call sfree (sp) +end + + +# SCAT_FREE -- Free scattered light memory. + +procedure scat_free () + +pointer ic1, ic2, gt1, gt2 +pointer sp, str + +int ic_geti() +real ic_getr() + +common /aps_com/ ic1, ic2, gt1, gt2 + +begin + if (ic1 != NULL) { + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + + call ic_gstr (ic1, "function", Memc[str], SZ_LINE) + call clpstr ("apscat1.function", Memc[str]) + call ic_gstr (ic1, "sample", Memc[str], SZ_LINE) + call clpstr ("apscat1.sample", Memc[str]) + call clputi ("apscat1.order", ic_geti (ic1, "order")) + call clputi ("apscat1.naverage", ic_geti (ic1, "naverage")) + call clputi ("apscat1.niterate", ic_geti (ic1, "niterate")) + call clputr ("apscat1.low", ic_getr (ic1, "low")) + call clputr ("apscat1.high", ic_getr (ic1, "high")) + call clputr ("apscat1.grow", ic_getr (ic1, "grow")) + + call ic_gstr (ic2, "function", Memc[str], SZ_LINE) + call clpstr ("apscat2.function", Memc[str]) + call ic_gstr (ic2, "sample", Memc[str], SZ_LINE) + call clpstr ("apscat2.sample", Memc[str]) + call clputi ("apscat2.order", ic_geti (ic2, "order")) + call clputi ("apscat2.naverage", ic_geti (ic2, "naverage")) + call clputi ("apscat2.niterate", ic_geti (ic2, "niterate")) + call clputr ("apscat2.low", ic_getr (ic2, "low")) + call clputr ("apscat2.high", ic_getr (ic2, "high")) + call clputr ("apscat2.grow", ic_getr (ic2, "grow")) + + call ic_closer (ic1) + call gt_free (gt1) + call ic_closer (ic2) + call gt_free (gt2) + call sfree (sp) + } +end + + +# AP_SMOOTH -- Smooth the scattered light by fitting one dimensional functions. +# +# The output image consists of smooth one dimensional fits across the +# dispersion. This routine reads each line along the dispersion and fits +# a function to smooth the fits made across the dispersion. The output +# image is used both as input of the cross dispersion fits and as output +# of the scattered light subtracted image. + +procedure ap_smooth (in, out, aaxis, daxis, aps, naps, ic, gt, cvs) + +pointer in # Input IMIO pointer +pointer out # Output IMIO pointer +int aaxis, daxis # Aperture and dispersion axes +pointer aps[ARB] # Apertures +int naps # Number of apertures +pointer ic # ICFIT pointer +pointer gt # GTOOLS pointer +pointer cvs # CURFIT pointers + +int i, npts, nlines, new +pointer cv, gp, indata, outdata, x, w + +int ap_gline(), ap_gdata() +bool clgetb(), apgansb() + +begin + if (!apgansb ("anssmooth")) + return + + # Allocate memory for curve fitting. + npts = IM_LEN (in, daxis) + nlines = IM_LEN (in, aaxis) + call salloc (x, npts, TY_REAL) + call salloc (w, npts, TY_REAL) + + do i = 1, npts + Memr[x+i-1] = i + call amovkr (1., Memr[w], npts) + call ic_putr (ic, "xmin", Memr[x]) + call ic_putr (ic, "xmax", Memr[x+npts-1]) + + # If the interactive flag is set then use icg_fit to set the + # fitting parameters. AP_GLINE returns EOF when the user + # is done. + + if (apgansb ("ansfitsmooth")) { + call ap_gopen (gp) + + i = nlines / 2 + outdata = NULL + while (ap_gline (ic, gt, cvs, out, daxis, aaxis, i, outdata) != + EOF) { + call icg_fit (ic, gp, "gcur", gt, cv, Memr[x], + Memr[outdata], Memr[w], npts) + call amovkr (1., Memr[w], npts) + } + call mfree (outdata, TY_REAL) + } + + # Loop through the input image and create an output image. + if (clgetb ("verbose")) { + call printf ("Smoothing scattered light along the dispersion ...\n") + call flush (STDOUT) + } + + # Use the new flag to optimize the fitting. + new = YES + i = 0 + while (ap_gdata (in, out, cvs, daxis, MAXBUF, i, + indata, outdata) != EOF) { + call ic_fit (ic, cv, Memr[x], Memr[outdata], Memr[w], npts, + new, YES, new, new) + call cvvector (cv, Memr[x], Memr[outdata], npts) + call asubr (Memr[indata], Memr[outdata], Memr[outdata], npts) + new = NO + } + call cvfree (cv) +end + + +# AP_GSCATTER -- Get scattered light pixels. +# +# The pixels outside the apertures extended by the specified buffer +# distance are selected. The x and weight arrays are also set. +# The apertures must be sorted by position. + +procedure ap_gscatter1 (aps, naps, line, data, npts, x, y, w, nscatter) + +pointer aps[naps] # Apertures +int naps # Number of apertures +int line # Line +real data[npts] # Image data +int npts # Number of points +real x[npts] # Scattered light positions +real y[npts] # Image data +real w[npts] # Weights +int nscatter # Number of scattered light pixels + +real buf # Aperture buffer + +int i, j, axis +int low, high +real center, ap_cveval(), clgetr() + +begin + buf = clgetr ("buffer") + 0.5 + call aclrr (x, npts) + + axis = AP_AXIS(aps[1]) + do i = 1, naps { + center = AP_CEN(aps[i],axis) + ap_cveval (AP_CV(aps[i]), real(line)) + low = max (1, int (center + AP_LOW(aps[i],axis) - buf)) + high = min (npts, int (center + AP_HIGH(aps[i],axis) + buf)) + do j = low, high + x[j] = 1 + } + + nscatter = 0 + do i = 1, npts { + if (x[i] == 0.) { + nscatter = nscatter + 1 + x[nscatter] = i + y[nscatter] = data[i] + w[nscatter] = 1. + } + } +end + + +# AP_GDATA -- Get the next line of image data. Return EOF at end. +# This task optimizes column access if needed. It assumes sequential access. + +int procedure ap_gdata (in, out, cvs, axis, maxbuf, index, indata, outdata) + +pointer in # Input IMIO pointer +pointer out # Output IMIO pointer (NULL if no output) +pointer cvs # CURFIT pointers +int axis # Image axis +int maxbuf # Maximum buffer size chars for column axis +int index # Last line (input), current line (returned) +pointer indata # Input data pointer +pointer outdata # Output data pointer + +real val, ap_cveval() +int i, last_index, col1, col2, nc, nd, ncols, nlines, ncols_block +pointer inbuf, outbuf, ptr, imgl2r(), impl2r(), imgs2r(), imps2r() + +begin + # Increment to the next image vector. + index = index + 1 + + # Initialize for the first vector. + if (index == 1) { + ncols = IM_LEN (in, 1) + if (IM_NDIM (in) == 1) + nlines = 1 + else + nlines = IM_LEN (in, 2) + + switch (axis) { + case 1: + nd = ncols + last_index = nlines + case 2: + nd = nlines + last_index = ncols + ncols_block = + max (1, min (ncols, maxbuf / nlines)) + col2 = 0 + + call malloc (indata, nlines, TY_REAL) + if (out != NULL) + call malloc (outdata, nlines, TY_REAL) + } + } + + # Finish up if the last vector has been done. + if (index > last_index) { + if (axis == 2) { + call mfree (indata, TY_REAL) + if (out != NULL) { + ptr = outbuf + index - 1 - col1 + do i = 1, nlines { + Memr[ptr] = Memr[outdata+i-1] + ptr = ptr + nc + } + call mfree (outdata, TY_REAL) + } + } + index = 0 + return (EOF) + } + + # Get the next image vector. + switch (axis) { + case 1: + indata = imgl2r (in, index) + if (out != NULL) + outdata = impl2r (out, index) + case 2: + if (out != NULL) + if (index > 1) { + ptr = outbuf + index - 1 - col1 + do i = 1, nlines { + Memr[ptr] = Memr[outdata+i-1] + ptr = ptr + nc + } + } + + if (index > col2) { + col1 = col2 + 1 + col2 = min (ncols, col1 + ncols_block - 1) + nc = col2 - col1 + 1 + inbuf = imgs2r (in, col1, col2, 1, nlines) + if (out != NULL) + outbuf = imps2r (out, col1, col2, 1, nlines) + } + + ptr = inbuf + index - col1 + do i = 1, nlines { + Memr[indata+i-1] = Memr[ptr] + ptr = ptr + nc + } + } + if (cvs != NULL) { + val = index + do i = 1, nd + Memr[outdata+i-1] = ap_cveval (Memi[cvs+i-1], val) + } + + return (index) +end + + +define CMDS "|quit|line|column|buffer|" +define QUIT 1 # Quit +define LINE 2 # Line to examine +define COLUMN 3 # Column to examine +define BUFFER 4 # Buffer distance + +# AP_GLINE -- Get image data to be fit interactively. Return EOF +# when the user enters EOF or CR. The out of bounds +# requests are silently limited to the nearest edge. + +int procedure ap_gline (ic, gt, cvs, im, axis, aaxis, line, data) + +pointer ic # ICFIT pointer +pointer gt # GTOOLS pointer +pointer cvs # CURFIT pointers +pointer im # IMIO pointer +int axis # Image axis +int aaxis # Aperture axis +int line # Line to get +pointer data # Image data + +real rval, clgetr(), ap_cveval() +int i, stat, cmd, ival, strdic(), scan(), nscan() +pointer sp, name, str, imgl2r(), imgs2r() + +begin + call smark (sp) + call salloc (name, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + + stat = OK + if (data != NULL) { + cmd = 0 + repeat { + switch (cmd) { + case QUIT: + stat = EOF + break + case LINE: + call gargi (ival) + if (axis == 2 || nscan() == 1) { + call printf ("line %d - ") + call pargi (line) + } else { + line = max (1, min (IM_LEN(im,2), ival)) + break + } + case COLUMN: + call gargi (ival) + if (axis == 1 || nscan() == 1) { + call printf ("column %d - ") + call pargi (line) + } else { + line = max (1, min (IM_LEN(im,1), ival)) + break + } + case BUFFER: + if (axis == aaxis) { + call gargr (rval) + if (nscan() == 1) { + call printf ("buffer %g - ") + call pargr (clgetr ("buffer")) + } else { + call clputr ("buffer", rval) + break + } + } + } + + if (axis == aaxis) { + if (axis == 1) + call printf ( + "Command (quit, buffer <value>, line <value>): ") + else + call printf ( + "Command (quit, buffer <value>, column <value>): ") + } else { + if (axis == 1) + call printf ( + "Command (quit, line <value>): ") + else + call printf ( + "Command (quit, column <value>): ") + } + call flush (STDOUT) + stat = scan () + if (stat == EOF) + break + call gargwrd (Memc[str], SZ_LINE) + cmd = strdic (Memc[str], Memc[str], SZ_LINE, CMDS) + } + + } + + if (stat != EOF) { + call imstats (im, IM_IMAGENAME, Memc[name], SZ_FNAME) + switch (axis) { + case 1: + call sprintf (Memc[str], SZ_LINE, "%s: Fit line %d\n%s") + call pargstr (Memc[name]) + call pargi (line) + call pargstr (IM_TITLE(im)) + call gt_sets (gt, GTTITLE, Memc[str]) + call ic_pstr (ic, "xlabel", "Column") + if (axis == aaxis) + data = imgl2r (im, line) + else { + if (data == NULL) + call malloc (data, IM_LEN(im,1), TY_REAL) + rval = line + do i = 1, IM_LEN(im,1) + Memr[data+i-1] = ap_cveval (Memi[cvs+i-1], rval) + } + case 2: + call sprintf (Memc[str], SZ_LINE, "%s: Fit column %d\n%s") + call pargstr (Memc[name]) + call pargi (line) + call pargstr (IM_TITLE(im)) + call gt_sets (gt, GTTITLE, Memc[str]) + call ic_pstr (ic, "xlabel", "Line") + if (axis == aaxis) + data = imgs2r (im, line, line, 1, IM_LEN(im,2)) + else { + if (data == NULL) + call malloc (data, IM_LEN(im,2), TY_REAL) + rval = line + do i = 1, IM_LEN(im,2) + Memr[data+i-1] = ap_cveval (Memi[cvs+i-1], rval) + } + } + } + + call sfree (sp) + return (stat) +end diff --git a/noao/twodspec/apextract/apselect.x b/noao/twodspec/apextract/apselect.x new file mode 100644 index 00000000..47730f47 --- /dev/null +++ b/noao/twodspec/apextract/apselect.x @@ -0,0 +1,40 @@ +include "apertures.h" + +define NRANGES 100 + + +# AP_SELECT -- Select apertures. +# The AP_SELECT field of the aperture structure is set. + +procedure ap_select (apertures, aps, naps) + +char apertures[ARB] #I Aperture selection string +pointer aps[ARB] #U Aperture pointers +int naps #I Number of apertures + +pointer sp, ranges +int i, decode_ranges() +bool is_in_range() + +begin + # Check if apertures are defined. + if (naps < 1) + return + + call smark (sp) + call salloc (ranges, 3*NRANGES, TY_INT) + + # Decode aperture string. + if (decode_ranges (apertures, Memi[ranges], NRANGES, i) == ERR) + call error (0, "Bad aperture list") + + # Select apertures. + do i = 1, naps { + if (is_in_range (Memi[ranges], AP_ID(aps[i]))) + AP_SELECT(aps[i]) = YES + else + AP_SELECT(aps[i]) = NO + } + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apshow.x b/noao/twodspec/apextract/apshow.x new file mode 100644 index 00000000..16f4d504 --- /dev/null +++ b/noao/twodspec/apextract/apshow.x @@ -0,0 +1,46 @@ +include "apertures.h" + +# AP_SHOW -- List the apertures to a text file. + +procedure ap_show (file, aps, naps) + +char file[ARB] # Aperture file +pointer aps[ARB] # Aperture pointers +int naps # Number of apertures + +pointer ap +int i, apaxis, fd, open() +errchk open + +begin + if (naps == 0) + return + + # Open the output file. Return if an error occurs. + fd = open (file, APPEND, TEXT_FILE) + + call fprintf (fd, "# APERTURES\n\n%4s %4s %7s %7s %7s %s\n") + call pargstr ("##ID") + call pargstr ("BEAM") + call pargstr ("CENTER") + call pargstr ("LOW") + call pargstr ("HIGH") + call pargstr ("TITLE") + for (i = 1; i <= naps; i = i + 1) { + ap = aps[i] + apaxis = AP_AXIS(ap) + call fprintf (fd, "%4d %4d %7.2f %7.2f %7.2f") + call pargi (AP_ID(ap)) + call pargi (AP_BEAM(ap)) + call pargr (AP_CEN(ap, apaxis)) + call pargr (AP_LOW(ap, apaxis)) + call pargr (AP_HIGH(ap, apaxis)) + if (AP_TITLE(ap) != NULL) { + call fprintf (fd, " %s") + call pargstr (Memc[AP_TITLE(ap)]) + } + call fprintf (fd, "\n") + } + + call close (fd) +end diff --git a/noao/twodspec/apextract/apskyeval.x b/noao/twodspec/apextract/apskyeval.x new file mode 100644 index 00000000..05f47f14 --- /dev/null +++ b/noao/twodspec/apextract/apskyeval.x @@ -0,0 +1,368 @@ +include <math/iminterp.h> +include <mach.h> +include "apertures.h" + +# Background fitting types +define BACKGROUND "|none|average|median|minimum|fit|" +define B_NONE 1 +define B_AVERAGE 2 +define B_MEDIAN 3 +define B_MINIMUM 4 +define B_FIT 5 + +define NSAMPLE 20 # Maximum number of background sample regions + + +# AP_SKYEVAL -- Evaluate sky within aperture. +# +# The sky pixels specified by the background sample string are used to +# determine a sky function at each line which is then evaluated for each +# pixel in the aperture as given by the SBUF array with starting offsets +# given by XS. The fitting consists of either a straight average or a +# function fit using ICFIT. The sky regions are specified relative to the +# aperture center. To avoid systematics due to shifting of the aperture +# relative to the integer pixel positions the sky regions are linearly +# interpolated. The average uses the integral of the interpolation +# function within the sample region endpoints. The fit samples the +# interpolation on a pixel grid with the aperture exactly centered on +# a pixel. A crude sky variance is computed for each line based solely +# on the variance model and the square root of the number of "pixels" +# used for the fit. This variance is used to boost the variance of +# the sky subtracted spectrum during variance weighting. Because sky +# noise may be significant in short slits a box car smoothing may be +# used giving a lower variance per pixel but bad errors near sky lines. +# An unweighted aperture sum of the sky is returned in case the user +# wants to save the subtracted 1D sky spectrum. + +procedure ap_skyeval (im, ap, dbuf, nc, nl, c1, l1, sbuf, svar, sky, nx, ny, + xs, ys, nsubaps, rdnoise) + +pointer im # IMIO pointer +pointer ap # Aperture structure +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +real sbuf[nx,ny] # Sky values +real svar[ny] # Sky variances +real sky[ny,nsubaps] # Extracted sky (out) +int nx, ny # Size of profile array +int xs[ny], ys # Origin of profile array +int nsubaps # Number of subapertures +real rdnoise # Readout noise in RMS data numbers. + +int bkg # Background type +int skybox # Sky box car smoothing + +int i, j, ix1, ix2, nsample, nsky, nfit, ix, iy +real center, xmin, xmax, a, b, c, s, avg +pointer ic, cv, cv1, asi, sp, str, data, as, bs, x, y, w + +int apgwrd(), apgeti(), ctor() +real ic_getr(), ap_cveval(), asieval(), asigrl(), amedr() +errchk salloc, ic_fit + +begin + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + + # Get CL parameters and set shift and fitting function pointers. + bkg = apgwrd ("background", Memc[str], SZ_LINE, BACKGROUND) + skybox = apgeti ("skybox") + + cv = AP_CV(ap) + ic = AP_IC(ap) + + # Set center and maximum limits relative to data buffer. + # The limits are required to overlap the aperture and include + # an extra point at each end for interpolation. Shifts + # and boundary limits will be enforced later. + + i = AP_AXIS(ap) + center = AP_CEN(ap,i) + xmin = center + min (AP_LOW(ap,i), ic_getr (ic, "xmin")) + xmax = center + max (AP_HIGH(ap,i), ic_getr (ic, "xmax")) + ix1 = nint (xmin) - 1 + ix2 = nint (xmax) + 1 + nfit = ix2 - ix1 + 1 + + # Allocate memory and parse sample string. + # The colons in the sample string must be changed to avoid + # sexigesimal interpretation. + + call salloc (as, NSAMPLE, TY_REAL) + call salloc (bs, NSAMPLE, TY_REAL) + + call ic_gstr (ic, "sample", Memc[str], SZ_LINE) + for (i=str; Memc[i]!=EOS; i=i+1) + if (Memc[i] == ':') + Memc[i] = '$' + + nsample = 0 + for (i=1; Memc[str+i-1]!=EOS; i=i+1) { + if (ctor (Memc[str], i, a) > 0) { + i = i - 1 + if (Memc[str+i] == '$') { + i = i + 2 + if (ctor (Memc[str], i, b) > 0) { + i = i - 1 + Memr[as+nsample] = center + min (a, b) + Memr[bs+nsample] = center + max (a, b) + nsample = nsample + 1 + if (nsample == NSAMPLE) + break + } + } + } + } + + if (nsample == 0) { + Memr[as] = xmin + Memr[bs] = xmax + nsample = 1 + } + + if (bkg == B_MEDIAN) + call salloc (y, nfit, TY_REAL) + else if (bkg == B_FIT) { + call salloc (x, nfit, TY_REAL) + call salloc (y, nfit, TY_REAL) + call salloc (w, nfit, TY_REAL) + } + + # Initialize the image interpolator. + call asiinit (asi, II_LINEAR) + + # Determine sky at each dispersion point. + call aclrr (svar, ny) + do iy = 1, ny { + + # Fit image interpolation function including extra points + # and apply image boundary limits. + + i = iy + ys - 1 + s = ap_cveval (cv, real (i)) + ix1 = max (c1, nint (xmin + s) - 1) + ix2 = min (c1+nc-1, nint (xmax + s) + 1) + nfit = ix2 - ix1 + 1 + if (nfit < 3) { + call aclrr (sbuf[1,iy], nx) + svar[iy] = 0. + next + } + data = dbuf + (i - l1) * nc + ix1 - c1 + if (bkg == B_AVERAGE || bkg == B_FIT) { + iferr (call asifit (asi, Memr[data], nfit)) { + call aclrr (sbuf[1,iy], nx) + svar[iy] = 0. + next + } + } + + # Determine background + switch (bkg) { + case B_AVERAGE: + # The background is computed by integrating the interpolator + avg = 0. + nsky = 0 + c = 0. + for (i=0; i < nsample; i=i+1) { + a = max (real (ix1), Memr[as+i] + s) - ix1 + 1 + b = min (real (ix2), Memr[bs+i] + s) - ix1 + 1 + if (b - a > 0.) { + avg = avg + asigrl (asi, a, b) + c = c + b - a + nsky = nsky + nint (b) - nint(a) + 1 + } + } + if (c > 0.) + avg = avg / c + call amovkr (avg, sbuf[1,iy], nx) + if (nsky > 1) + svar[iy] = max (0., (rdnoise + avg) / (nsky - 1)) + case B_MEDIAN: + # The background is computed by the median pixel + avg = 0. + nsky = 0 + for (i=0; i < nsample; i=i+1) { + a = max (real (ix1), Memr[as+i] + s) - ix1 + 1 + b = min (real (ix2), Memr[bs+i] + s) - ix1 + 1 + do j = nint (a), nint (b) { + Memr[y+nsky] = Memr[data+j-1] + nsky = nsky + 1 + } + } + if (nsky > 0) + avg = amedr (Memr[y], nsky) + call amovkr (avg, sbuf[1,iy], nx) + if (nsky > 1) + svar[iy] = max (0., (rdnoise + avg) / (nsky - 1)) + case B_MINIMUM: + # The background is computed by the minimum pixel + avg = MAX_REAL + nsky = 0 + for (i=0; i < nsample; i=i+1) { + a = max (real (ix1), Memr[as+i] + s) - ix1 + 1 + b = min (real (ix2), Memr[bs+i] + s) - ix1 + 1 + do j = nint (a), nint (b) { + avg = min (avg, Memr[data+j-1]) + nsky = nsky + 1 + } + } + if (nsky == 0) + avg = 0 + call amovkr (avg, sbuf[1,iy], nx) + if (nsky > 1) + svar[iy] = max (0., (rdnoise + avg) / (nsky - 1)) + case B_FIT: + # The fitting is done in a coordinate system relative to + # aperture center. + + c = center + s + a = ix1 + c - int (c) + do i = 1, nfit-1 { + Memr[x+i-1] = nint (1000. * (a - c)) / 1000. + Memr[y+i-1] = asieval (asi, a-ix1+1) + Memr[w+i-1] = 1. + a = a + 1. + } + + iferr { + call ic_fit (ic, cv1, Memr[x], Memr[y], Memr[w], nfit-1, + YES, YES, YES, YES) + + avg = 0. + do i = 1, nx { + a = xs[iy] + i - 1 + b = ap_cveval (cv1, a - c) + avg = avg + b + sbuf[i,iy] = b + } + avg = avg / nx + } then { + avg = 0. + call aclrr (sbuf[1,iy], nx) + } + + nsky = 0. + for (i=0; i < nsample; i=i+1) { + a = max (real (ix1), Memr[as+i] + s) - ix1 + 1 + b = min (real (ix2), Memr[bs+i] + s) - ix1 + 1 + nsky = nsky + nint (b) - nint (a) + 1 + } + if (nsky > 1) + svar[iy] = max (0., (rdnoise + avg) / (nsky - 1)) + } + } + + # Do box car smoothing if desired. + if (skybox > 1) { + ix2 = skybox ** 2 + avg = 0. + a = 0. + iy = 1 + for (i=1; i<=skybox; i=i+1) { + avg = avg + sbuf[1,i] + a = a + svar[i] + } + for (; i<=ny; i=i+1) { + b = sbuf[1,iy] + c = svar[iy] + sbuf[1,iy] = avg / skybox + svar[iy] = a / ix2 + avg = avg + sbuf[1,i] - b + a = a + svar[i] - c + iy = iy + 1 + } + sbuf[1,iy] = avg / skybox + svar[iy] = a / ix2 + i = ny - skybox + 1 + for (iy=ny; iy > ny-skybox/2; iy=iy-1) + svar[iy] = svar[i] + for (; i > 1; i=i-1) { + svar[iy] = svar[i] + iy = iy - 1 + } + for (; iy > 1; iy=iy-1) + svar[iy] = svar[1] + + switch (bkg) { + case B_AVERAGE, B_MEDIAN, B_MINIMUM: + i = ny - skybox + 1 + for (iy=ny; iy > ny-skybox/2; iy=iy-1) + call amovkr (sbuf[1,i], sbuf[1,iy], nx) + for (; i > 1; i=i-1) { + call amovkr (sbuf[1,i], sbuf[1,iy], nx) + iy = iy - 1 + } + for (; iy > 1; iy=iy-1) + call amovkr (sbuf[1,1], sbuf[1,iy], nx) + case B_FIT: + i = ny - skybox + 1 + for (iy=ny; iy > ny-skybox/2; iy=iy-1) + sbuf[1,iy] = sbuf[1,i] + for (; i > 1; i=i-1) { + sbuf[1,iy] = sbuf[1,i] + iy = iy - 1 + } + for (; iy > 1; iy=iy-1) + sbuf[1,iy] = sbuf[1,1] + do ix1 = 2, nx { + avg = 0. + iy = 1 + for (i=1; i<=skybox; i=i+1) + avg = avg + sbuf[ix1,i] + for (; i<=ny; i=i+1) { + b = sbuf[ix1,iy] + sbuf[ix1,iy] = avg / skybox + avg = avg + sbuf[ix1,i] - b + iy = iy + 1 + } + sbuf[ix1,iy] = avg / skybox + i = ny - skybox + 1 + for (iy=ny; iy > ny-skybox/2; iy=iy-1) + sbuf[ix1,iy] = sbuf[ix1,i] + for (; i > 1; i=i-1) { + sbuf[ix1,iy] = sbuf[ix1,i] + iy = iy - 1 + } + for (; iy > 1; iy=iy-1) + sbuf[ix1,iy] = sbuf[ix1,1] + } + } + } + + # Compute the unweighted aperture sky spectrum. + i = AP_AXIS(ap) + a = AP_CEN(ap,i) + AP_LOW(ap,i) + b = AP_CEN(ap,i) + AP_HIGH(ap,i) + c = (b - a) / nsubaps + + do iy = 1, ny { + data = dbuf + (iy + ys - 1 - l1) * nc + xs[iy] - c1 - 1 + s = ap_cveval (cv, real (iy + ys - 1)) - c1 + 1 + do i = 1, nsubaps { + xmin = max (0.5, a + (i - 1) * c + s) + c1 - xs[iy] + xmax = min (nc + 0.49, a + i * c + s) + c1 - xs[iy] + if (xmin >= xmax) { + sky[iy,i] = 0. + next + } + ix1 = nint (xmin) + ix2 = nint (xmax) + + if (ix1 == ix2) + sky[iy,i] = (xmax - xmin) * sbuf[ix1,iy] + else { + sky[iy,i] = (ix1 - xmin + 0.5) * sbuf[ix1,iy] + sky[iy,i] = sky[iy,i] + (xmax - ix2 + 0.5) * sbuf[ix2,iy] + } + do ix = ix1+1, ix2-1 + sky[iy,i] = sky[iy,i] + sbuf[ix,iy] + } + } + + if (bkg == B_FIT) + call cvfree (cv1) + call asifree (asi) + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apsort.x b/noao/twodspec/apextract/apsort.x new file mode 100644 index 00000000..85b21cc5 --- /dev/null +++ b/noao/twodspec/apextract/apsort.x @@ -0,0 +1,55 @@ +include "apertures.h" + +# Sort flags: +define INC 1 # Sort by aperture position in increasing order +define DEC 2 # Sort by position in decreasing order + +# AP_SORT -- Sort the apertures. + +procedure ap_sort (current, aps, naps, flag) + +int current # Current aperture +pointer aps[ARB] # Aperture data +int naps # Number of apertures +int flag # Sort flag + +int i, j, apaxis +pointer ap + +begin + if (naps < 1) + return + + switch (flag) { + case INC: + apaxis = AP_AXIS (aps[1]) + for (i = 1; i <= naps - 1; i = i + 1) { + for (j = i + 1; j <= naps; j = j + 1) { + if (AP_CEN(aps[i], apaxis) > AP_CEN(aps[j], apaxis)) { + ap = aps[i] + aps[i] = aps[j] + aps[j] = ap + if (current == i) + current = j + else if (current == j) + current = i + } + } + } + case DEC: + apaxis = AP_AXIS (aps[1]) + for (i = 1; i <= naps - 1; i = i + 1) { + for (j = i + 1; j <= naps; j = j + 1) { + if (AP_CEN(aps[i], apaxis) < AP_CEN(aps[j], apaxis)) { + ap = aps[i] + aps[i] = aps[j] + aps[j] = ap + if (current == i) + current = j + else if (current == j) + current = i + } + } + } + } +end diff --git a/noao/twodspec/apextract/apsum.par b/noao/twodspec/apextract/apsum.par new file mode 100644 index 00000000..b5b58013 --- /dev/null +++ b/noao/twodspec/apextract/apsum.par @@ -0,0 +1,34 @@ +# APSUM + +input,s,a,,,,List of input images +output,s,h,"",,,List of output spectra +apertures,s,h,"",,,Apertures +format,s,h,"multispec","onedspec|multispec|echelle|strip",,Extracted spectra format +references,s,h,"",,,List of aperture reference images +profiles,s,h,"",,,"List of aperture profile images +" +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,no,,,Recenter apertures? +resize,b,h,no,,,Resize apertures? +edit,b,h,yes,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,Fit the traced points interactively? +extract,b,h,yes,,,Extract apertures? +extras,b,h,no,,,"Extract sky, sigma, etc.?" +review,b,h,yes,,,"Review extractions? +" +line,i,h,INDEF,1,,Dispersion line +nsum,i,h,10,,,"Number of dispersion lines to sum or median +" +background,s,h,"none",,,Background to subtract (none|average|fit) +weights,s,h,"none","none|variance",,Extraction weights (none|variance) +pfit,s,h,"fit1d","fit1d|fit2d",,Profile fitting type (fit1d|fit2d) +clean,b,h,no,,,Detect and replace bad pixels? +skybox,i,h,1,1,,Box car smoothing length for sky +saturation,r,h,INDEF,,,Saturation level +readnoise,s,h,"0.",,,Read out noise sigma (photons) +gain,s,h,"1.",,,Photon gain (photons/data number) +lsigma,r,h,4.,0.,,Lower rejection threshold +usigma,r,h,4.,0.,,Upper rejection threshold +nsubaps,i,h,1,1,,Number of subapertures per aperture diff --git a/noao/twodspec/apextract/aptrace.par b/noao/twodspec/apextract/aptrace.par new file mode 100644 index 00000000..9134a012 --- /dev/null +++ b/noao/twodspec/apextract/aptrace.par @@ -0,0 +1,27 @@ +# APTRACE + +input,s,a,,,,List of input images to trace +apertures,s,h,"",,,Apertures +references,s,h,"",,,List of reference images + +interactive,b,h,yes,,,Run task interactively? +find,b,h,yes,,,Find apertures? +recenter,b,h,no,,,Recenter apertures? +resize,b,h,no,,,Resize apertures? +edit,b,h,no,,,Edit apertures? +trace,b,h,yes,,,Trace apertures? +fittrace,b,h,yes,,,"Fit the traced points interactively? +" +line,i,h,INDEF,1,,Starting dispersion line +nsum,i,h,10,,,Number of dispersion lines to sum +step,i,h,10,1,,Tracing step +nlost,i,h,3,1,,"Number of consecutive times profile is lost before quitting +" +function,s,h,"legendre","chebyshev|legendre|spline1|spline3",,Trace fitting function +order,i,h,2,1,,Trace fitting function order +sample,s,h,"*",,,Trace sample regions +naverage,i,h,1,,,Trace average or median +niterate,i,h,0,0,,Trace rejection iterations +low_reject,r,h,3.,0.,,Trace lower rejection sigma +high_reject,r,h,3.,0.,,Trace upper rejection sigma +grow,r,h,0.,0.,,Trace rejection growing radius diff --git a/noao/twodspec/apextract/aptrace.x b/noao/twodspec/apextract/aptrace.x new file mode 100644 index 00000000..c38af01c --- /dev/null +++ b/noao/twodspec/apextract/aptrace.x @@ -0,0 +1,669 @@ +include <imhdr.h> +include <math/curfit.h> +include <pkg/center1d.h> +include <pkg/gtools.h> +include "apertures.h" + +define MAXBUF 100000 # Column buffer size + + +# AP_TRACE -- Trace features in a two dimensional image. +# +# Given an image pointer, the starting dispersion position, and a set +# of apertures defining the centers of features, trace the feature +# centers to other dispersion positions and fit a curve to the positions. +# The user specifies the dispersion step size, the number of dispersion +# lines to sum, and parameters for the feature centering function +# fitting. + +procedure ap_trace (image, line, aps, naps, apedit) + +char image[SZ_FNAME] # Image name +int line # Starting dispersion position +pointer aps[ARB] # Apertures +int naps # Number of apertures +int apedit # Called from APEDIT? + +int step # Tracing step +int nsum # Number of dispersion lines to sum +int nlost # Number of steps lost before quitting +real cradius # Centering radius +real cwidth # Centering width +real cthreshold # Detection threshold for centering + +int i, na, dispaxis, apaxis +real center +pointer im, ic, ic1, sp, str +data ic1 /NULL/ + +int apgeti() +real apgetr() +bool clgetb(), ap_answer() +pointer ap_immap() + +errchk ap_immap, ic_open, ap_ltrace, ap_ctrace, ap_default + +common /apt_com/ ic + +begin + na = 0 + do i = 1, naps + if (AP_SELECT(aps[i]) == YES) + na = na + 1 + if (naps > 0 && na == 0) + return + + # Query user. + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + if (apedit == NO) { + call sprintf (Memc[str], SZ_LINE, "Trace apertures for %s?") + call pargstr (image) + if (!ap_answer ("anstrace", Memc[str])) { + call sfree (sp) + return + } + + call sprintf (Memc[str], SZ_LINE, + "Fit traced positions for %s interactively?") + call pargstr (image) + if (ap_answer ("ansfittrace", Memc[str])) { + call apgstr ("ansfittrace", Memc[str], SZ_LINE) + call appstr ("ansfittrace1", Memc[str]) + } else + call appstr ("ansfittrace1", "NO") + + if (clgetb ("verbose")) + call printf ("Tracing apertures ...\n") + } + + # Tracing parameters + step = apgeti ("t_step") + nsum = max (1, abs (apgeti ("t_nsum"))) + nlost = apgeti ("t_nlost") + if (ic == NULL || ic1 == NULL) { + call ic_open (ic) + ic1 = ic + call apgstr ("t_function", Memc[str], SZ_LINE) + call ic_pstr (ic, "function", Memc[str]) + call ic_puti (ic, "order", apgeti ("t_order")) + call apgstr ("t_sample", Memc[str], SZ_LINE) + call ic_pstr (ic, "sample", Memc[str]) + call ic_puti (ic, "naverage", apgeti ("t_naverage")) + call ic_puti (ic, "niterate", apgeti ("t_niterate")) + call ic_putr (ic, "low", apgetr ("t_low_reject")) + call ic_putr (ic, "high", apgetr ("t_high_reject")) + call ic_putr (ic, "grow", apgetr ("t_grow")) + } + + im = ap_immap (image, apaxis, dispaxis) + + # If no apertures are defined default to the center of the image. + if (naps == 0) { + naps = 1 + center = IM_LEN (im, apaxis) / 2. + call ap_default (im, 1, 1, apaxis, center, real (line), + aps[naps]) + call sprintf (Memc[str], SZ_LINE, + "TRACE - Default aperture defined centered on %s") + call pargstr (image) + call ap_log (Memc[str], YES, NO, YES) + } + + # Centering parameters + cwidth = apgetr ("t_width") + cradius = apgetr ("radius") + cthreshold = apgetr ("threshold") + + switch (dispaxis) { + case 1: + call ap_ctrace (image, im, ic, line, step, nsum, nlost, cradius, + cwidth, cthreshold, aps, naps) + case 2: + call ap_ltrace (image, im, ic, line, step, nsum, nlost, cradius, + cwidth, cthreshold, aps, naps) + } + + # Log the tracing and write the traced apertures to the database. + + call sprintf (Memc[str], SZ_LINE, + "TRACE - %d apertures traced in %s.") + call pargi (na) + call pargstr (image) + if (apedit == NO) + call ap_log (Memc[str], YES, YES, NO) + else + call ap_log (Memc[str], YES, NO, NO) + + call appstr ("ansdbwrite1", "yes") + + call imunmap (im) + call sfree (sp) +end + + +procedure ap_trfree () + +pointer ic +common /apt_com/ ic + +begin + call ic_closer (ic) +end + + +# AP_CTRACE -- Trace feature positions for aperture axis 2. + +procedure ap_ctrace (image, im, ic, start, step, nsum, nlost, cradius, cwidth, + threshold, aps, naps) + +char image[ARB] # Image to be traced. +pointer im # IMIO pointer +pointer ic # ICFIT pointer +int start # Starting column +int step # Tracing step size +int nsum # Number of lines or columns to sum +int nlost # Number of steps lost before quiting +real cradius # Centering radius +real cwidth # Centering width +real threshold # Detection threshold for centering +pointer aps[ARB] # Apertures +int naps # Number of apertures + +int nlines, col, col1, col2, line1, line2 +int i, j, n, nx, ny, ntrace, istart, lost, fd +real yc, yc1 +pointer co, data, sp, str, x, y, wts, gp, gt + +real center1d(), ap_cveval() +bool ap_answer() +pointer comap(), gt_init() + +errchk ap_cveval, xt_csum, xt_csumb, center1d, icg_fit, ic_fit +errchk ap_gopen, ap_popen + +begin + # Set up column access buffering. + + co = comap (im, MAXBUF) + + # Determine the number of lines to be traced and allocate memory. + + nx = IM_LEN(im, 1) + ny = IM_LEN(im, 2) + if (IS_INDEFI (start)) + start = nx / 2 + nlines = 5 * cwidth + istart = (start - 1) / step + 1 + ntrace = istart + (nx - start) / step + + # Allocate memory for the traced positions and the weights for fitting. + + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (x, ntrace, TY_REAL) + call salloc (y, ntrace, TY_REAL) + call salloc (wts, ntrace, TY_REAL) + call aclrr (Memr[y], ntrace) + data = NULL + + # Initialize the ICFIT limits and the GTOOLS parameters. + # Set initial interactive flag. + + call ic_putr (ic, "xmin", 1.) + call ic_putr (ic, "xmax", real (nx)) + call ic_pstr (ic, "xlabel", "Column") + call ic_pstr (ic, "ylabel", "Line") + + gt = gt_init() + call gt_setr (gt, GTXMIN, 1. - step / 2) + call gt_setr (gt, GTXMAX, real (nx + step / 2)) + + # Trace each feature. + + line1 = 0 + line2 = 0 + do j = 1, naps { + if (AP_SELECT(aps[j]) == NO) + next + + # Trace from the starting column to the last column while the + # position is not INDEF. + + lost = 0 + yc = AP_CEN(aps[j], 2) + ap_cveval (AP_CV(aps[j]), real (start)) + do i = istart, ntrace { + Memr[y+i-1] = INDEF + if (lost < nlost) { + # Update the scrolling buffer if the feature center is less + # than cwidth from the edge of the buffer. + if (((yc-line1) < cwidth) || ((line2-yc) < cwidth)) { + line1 = max (1, int (yc + .5 - nlines / 2)) + line2 = min (ny, line1 + nlines - 1) + line1 = max (1, line2 - nlines + 1) + } + + # Sum columns to form the 1D vector for centering. + + col = start + (i - istart) * step + col1 = max (1, col - nsum / 2) + col2 = min (nx, col1 + nsum - 1) + col1 = max (1, col2 - nsum + 1) + + # If columns in the sum overlap then use buffering. + + if (step < nsum) + call xt_csumb (co, col1, col2, line1, line2, data) + else + call xt_csum (co, col1, col2, line1, line2, data) + + # Center the feature for the new column using the previous + # center as the starting point. Convert to position + # relative to the start of the data buffer for centering + # and then convert back to position relative to the + # edge of the image. + + yc1 = center1d (yc-line1+1, Memr[data], line2-line1+1, + cwidth, EMISSION, cradius, threshold) + + if (!IS_INDEF (yc1)) { + lost = 0 + yc = yc1 + line1 - 1 + Memr[y+i-1] = yc + if (IS_INDEF (Memr[y+i-2])) { + call sprintf (Memc[str], SZ_LINE, + "TRACE - Trace of aperture %d in %s recovered at column %d.") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call pargi (col) + call ap_log (Memc[str], YES, NO, YES) + } + } else { + lost = lost + 1 + call sprintf (Memc[str], SZ_LINE, + "TRACE - Trace of aperture %d in %s lost at column %d.") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call pargi (col) + call ap_log (Memc[str], YES, NO, YES) + } + } + } + + # Trace from the starting column to the first column while the + # position is not INDEF. + + lost = 0 + yc = AP_CEN(aps[j], 2) + ap_cveval (AP_CV(aps[j]), real (start)) + do i = istart - 1, 1, -1 { + Memr[y+i-1] = INDEF + if (lost < nlost) { + # Update the scrolling buffer if the feature center is less + # than cwidth from the edge of the buffer. + + if (((yc-line1) < cwidth) || ((line2-yc) < cwidth)) { + line1 = max (1, int (yc + .5 - nlines / 2)) + line2 = min (ny, line1 + nlines - 1) + line1 = max (1, line2 - nlines + 1) + } + + # Sum columns to form the 1D vector for centering. + + col = start + (i - istart) * step + col1 = max (1, col - nsum / 2) + col2 = min (nx, col1 + nsum - 1) + col1 = max (1, col2 - nsum + 1) + + # If columns in the sum overlap then use buffering. + + if (step < nsum) + call xt_csumb (co, col1, col2, line1, line2, data) + else + call xt_csum (co, col1, col2, line1, line2, data) + + # Center the feature for the new column using the previous + # center as the starting point. Convert to position + # relative to the start of the data buffer for centering + # and then convert back to position relative to the + # edge of the image. + + yc1 = center1d (yc-line1+1, Memr[data], line2-line1+1, + cwidth, EMISSION, cradius, threshold) + + if (!IS_INDEF (yc1)) { + lost = 0 + yc = yc1 + line1 - 1 + Memr[y+i-1] = yc + if (IS_INDEF (Memr[y+i])) { + call sprintf (Memc[str], SZ_LINE, + "TRACE - Trace of aperture %d in %s recovered at column %d.") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call pargi ((i - 1) * step + 1) + call ap_log (Memc[str], YES, NO, YES) + } + } else { + lost = lost + 1 + call sprintf (Memc[str], SZ_LINE, + "TRACE - Trace of aperture %d in %s lost at column %d.") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call pargi ((i - 1) * step + 1) + call ap_log (Memc[str], YES, NO, YES) + } + } + } + + # Order the traced points and exclude INDEF positions. + + n = 0 + do i = 1, ntrace { + if (IS_INDEF (Memr[y+i-1])) + next + n = n + 1 + Memr[x+n-1] = start + (i - istart) * step + Memr[y+n-1] = Memr[y+i-1] + Memr[wts+n-1] = 1. + } + + # If all positions are INDEF print a message and go on to the next + # aperture. + + if (n < 2) { + call eprintf ( + "Not enough points traced for aperture %d of %s\n") + call pargi (AP_ID(aps[j])) + call pargstr (image) + next + } + + # Fit a curve to the traced positions and graph the result. + + call sprintf (Memc[str], SZ_LINE, "Aperture %d of %s") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call gt_sets (gt, GTTITLE, Memc[str]) + + call sprintf (Memc[str], SZ_LINE, + "Fit curve to aperture %d of %s interactively") + call pargi (AP_ID(aps[j])) + call pargstr (image) + if (ap_answer ("ansfittrace1", Memc[str])) { + call ap_gopen (gp) + call icg_fit (ic, gp, "gcur", gt, + AP_CV(aps[j]), Memr[x], Memr[y], Memr[wts], n) + } else + call ic_fit (ic, AP_CV(aps[j]), Memr[x], Memr[y], Memr[wts], n, + YES, YES, YES, YES) + + call ap_popen (gp, fd, "trace") + if (gp != NULL) { + call icg_graphr (ic, gp, gt, AP_CV(aps[j]), + Memr[x], Memr[y], Memr[wts], n) + call ap_pclose (gp, fd) + } + + call asubkr (Memr[y], AP_CEN(aps[j], 2), Memr[y], n) + call ic_fit (ic, AP_CV(aps[j]), Memr[x], Memr[y], Memr[wts], n, + YES, YES, YES, YES) + } + + # Free allocated memory. + + call gt_free (gt) + call mfree (data, TY_REAL) + call counmap (co) + call sfree (sp) +end + + +# AP_LTRACE -- Trace feature positions for aperture axis 1. + +procedure ap_ltrace (image, im, ic, start, step, nsum, nlost, cradius, cwidth, + threshold, aps, naps) + +char image[ARB] # Image to be traced +pointer im # IMIO pointer +pointer ic # ICFIT pointer +int start # Starting line +int step # Tracing step size +int nsum # Number of lines or columns to sum +int nlost # Number of steps lost before quiting +real cradius # Centering radius +real cwidth # Centering width +real threshold # Detection threshold for centering +pointer aps[ARB] # Apertures +int naps # Number of apertures + +real xc1 +int i, j, n, nx, ny, ntrace, istart, line, line1, line2, fd +pointer data, sp, str, x, y, wts, xc, lost, x1, x2, gp, gt + +real center1d(), ap_cveval() +bool ap_answer() +pointer gt_init() + +errchk ap_cveval, xt_lsum, xt_lsumb, center1d, icg_fit, ic_fit +errchk ap_gopen, ap_popen + +begin + # Determine the number of lines to be traced and allocate memory. + + nx = IM_LEN(im, 1) + ny = IM_LEN(im, 2) + if (IS_INDEFI (start)) + start = ny / 2 + + istart = (start - 1) / step + 1 + ntrace = istart + (ny - start) / step + + # Allocate memory for the traced positions and the weights for fitting. + + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (x, ntrace * naps, TY_REAL) + call salloc (y, ntrace, TY_REAL) + call salloc (wts, ntrace, TY_REAL) + call salloc (xc, naps, TY_REAL) + call salloc (lost, naps, TY_INT) + call aclrr ( Memr[x], ntrace * naps) + data = NULL + + # Set the dispersion lines to be traced. + + do i = 1, ntrace + Memr[y+i-1] = start + (i - istart) * step + + # Trace from the starting line to the last line. + + x1 = x + istart - 1 + do i = 1, naps { + if (AP_SELECT(aps[i]) == NO) + next + Memr[xc+i-1] = AP_CEN(aps[i], 1) + + ap_cveval (AP_CV(aps[i]), real (start)) + Memi[lost+i-1] = 0 + } + + do i = istart, ntrace { + line = Memr[y+i-1] + line1 = max (1, line - nsum / 2) + line2 = min (ny, line1 + nsum - 1) + line1 = max (1, line2 - nsum + 1) + + # If the sums overlap use buffering. + + if (step < nsum) + call xt_lsumb (im, 1, nx, line1, line2, data) + else + call xt_lsum (im, 1, nx, line1, line2, data) + + do j = 1, naps { + if (AP_SELECT(aps[j]) == NO) + next + x2 = x1 + (j - 1) * ntrace + Memr[x2] = INDEF + if (Memi[lost+j-1] < nlost) { + xc1 = center1d (Memr[xc+j-1], Memr[data], nx, + cwidth, EMISSION, cradius, threshold) + if (IS_INDEF(xc1)) { + Memi[lost+j-1] = Memi[lost+j-1] + 1 + call sprintf (Memc[str], SZ_LINE, + "TRACE - Trace of aperture %d in %s lost at line %d.") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call pargi (line) + call ap_log (Memc[str], YES, NO, YES) + } else { + Memi[lost+j-1] = 0 + Memr[xc+j-1] = xc1 + Memr[x2] = xc1 + if (IS_INDEF (Memr[x2-1])) { + call sprintf (Memc[str], SZ_LINE, + "TRACE - Trace of aperture %d in %s recovered at line %d.") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call pargi (line) + call ap_log (Memc[str], YES, NO, YES) + } + } + } + } + x1 = x1 + 1 + } + + # Trace from the starting line to the first line. + + x1 = x + istart - 2 + do i = 1, naps { + if (AP_SELECT(aps[i]) == NO) + next + Memr[xc+i-1] = AP_CEN(aps[i], 1) + + ap_cveval (AP_CV(aps[i]), real (start)) + Memi[lost+i-1] = 0 + } + + do i = istart - 1, 1, -1 { + line = Memr[y+i-1] + line1 = max (1, line - nsum / 2) + line2 = min (ny, line1 + nsum - 1) + line1 = max (1, line2 - nsum + 1) + + # If the sums overlap use buffering. + + if (step < nsum) + call xt_lsumb (im, 1, nx, line1, line2, data) + else + call xt_lsum (im, 1, nx, line1, line2, data) + + do j = 1, naps { + if (AP_SELECT(aps[j]) == NO) + next + x2 = x1 + (j - 1) * ntrace + Memr[x2] = INDEF + if (Memi[lost+j-1] < nlost) { + xc1 = center1d (Memr[xc+j-1], Memr[data], nx, + cwidth, EMISSION, cradius, threshold) + if (IS_INDEF(xc1)) { + Memi[lost+j-1] = Memi[lost+j-1] + 1 + call sprintf (Memc[str], SZ_LINE, + "TRACE - Trace of aperture %d in %s lost at line %d.") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call pargi (line) + call ap_log (Memc[str], YES, NO, YES) + } else { + Memi[lost+j-1] = 0 + Memr[xc+j-1] = xc1 + Memr[x2] = xc1 + if (IS_INDEF (Memr[x2+1])) { + call sprintf (Memc[str], SZ_LINE, + "TRACE - Trace of aperture %d in %s recovered at line %d.") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call pargi (line) + call ap_log (Memc[str], YES, NO, YES) + } + } + } + } + x1 = x1 - 1 + } + + # Initialize the the GTOOLS parameters. + call ic_putr (ic, "xmin", 1.) + call ic_putr (ic, "xmax", real (ny)) + call ic_pstr (ic, "xlabel", "Line") + call ic_pstr (ic, "ylabel", "Column") + + gt = gt_init() + call gt_setr (gt, GTXMIN, 1. - step / 2) + call gt_setr (gt, GTXMAX, real (ny + step / 2)) + + do j = 1, naps { + if (AP_SELECT(aps[j]) == NO) + next + + # Order the traced points and exclude INDEF positions. + + x1 = x + (j - 1) * ntrace + n = 0 + + do i = 1, ntrace { + if (IS_INDEF (Memr[x1+i-1])) + next + n = n + 1 + Memr[x1+n-1] = Memr[x1+i-1] + Memr[y+n-1] = start + (i - istart) * step + Memr[wts+n-1] = 1. + } + + # If all positions are INDEF print a message and go on to the next + # aperture. + + if (n < 2) { + call eprintf ( + "Not enough points traced for aperture %d of %s\n") + call pargi (AP_ID(aps[j])) + call pargstr (image) + next + } + + # Fit a curve to the traced positions and graph the result. + + call sprintf (Memc[str], SZ_LINE, "Aperture %d of %s") + call pargi (AP_ID(aps[j])) + call pargstr (image) + call gt_sets (gt, GTTITLE, Memc[str]) + + call sprintf (Memc[str], SZ_LINE, + "Fit curve to aperture %d of %s interactively") + call pargi (AP_ID(aps[j])) + call pargstr (image) + if (ap_answer ("ansfittrace1", Memc[str])) { + call ap_gopen (gp) + call icg_fit (ic, gp, "gcur", gt, + AP_CV(aps[j]), Memr[y], Memr[x1], Memr[wts], n) + } else + call ic_fit (ic, AP_CV(aps[j]), Memr[y], Memr[x1], Memr[wts], n, + YES, YES, YES, YES) + + call ap_popen (gp, fd, "trace") + if (gp != NULL) { + call icg_graphr (ic, gp, gt, AP_CV(aps[j]), + Memr[y], Memr[x1], Memr[wts], n) + call ap_pclose (gp, fd) + } + + # Subtract the aperture center and refit offset curve. + call asubkr (Memr[x1], AP_CEN(aps[j], 1), Memr[x1], n) + call ic_fit (ic, AP_CV(aps[j]), Memr[y], Memr[x1], Memr[wts], n, + YES, YES, YES, YES) + } + + # Free allocated memory. + + call gt_free (gt) + call mfree (data, TY_REAL) + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apupdate.x b/noao/twodspec/apextract/apupdate.x new file mode 100644 index 00000000..d3344b5f --- /dev/null +++ b/noao/twodspec/apextract/apupdate.x @@ -0,0 +1,44 @@ +include <gset.h> +include "apertures.h" + +# AP_UPDATE -- Update an aperture. + +procedure ap_update (gp, ap, line, apid, apbeam, center, low, high) + +pointer gp # GIO pointer +pointer ap # Aperture pointer +int line # Dispersion line +int apid # New aperture ID +int apbeam # New aperture beam +real center # New center at dispersion line +real low # New lower limit +real high # New upper limit + +real ap_cveval(), ic_getr() + +begin + # Check for bad values. + if (IS_INDEFR(center) || IS_INDEFR(low) || IS_INDEFR(high)) + call error (1, "INDEF not allowed") + + # Erase the current aperture. + call gseti (gp, G_PLTYPE, 0) + call ap_gmark (gp, line, ap, 1) + + # Update the aperture. + AP_ID(ap) = apid + AP_BEAM(ap) = apbeam + AP_CEN(ap, AP_AXIS(ap)) = center - ap_cveval (AP_CV(ap), real (line)) + AP_LOW(ap, AP_AXIS(ap)) = min (low, high) + AP_HIGH(ap, AP_AXIS(ap)) = max (low, high) + if (AP_IC(ap) != NULL) { + call ic_putr (AP_IC(ap), "xmin", + min (low, high, ic_getr (AP_IC(ap), "xmin"))) + call ic_putr (AP_IC(ap), "xmax", + max (low, high, ic_getr (AP_IC(ap), "xmax"))) + } + + # Mark the new aperture. + call gseti (gp, G_PLTYPE, 1) + call ap_gmark (gp, line, ap, 1) +end diff --git a/noao/twodspec/apextract/apvalues.x b/noao/twodspec/apextract/apvalues.x new file mode 100644 index 00000000..2072907e --- /dev/null +++ b/noao/twodspec/apextract/apvalues.x @@ -0,0 +1,32 @@ +include "apertures.h" + +# AP_VALUES -- Return the values for an aperture + +procedure ap_values (current, aps, line, apid, apbeam, center, low, high) + +int current # Index to current aperture +pointer aps[ARB] # Apertures +int line # Line +int apid # Aperture ID +int apbeam # Aperture beam +real center # Aperture center +real low # Lower limit of aperture +real high # Upper limit of aperture + +int apaxis +pointer ap + +real ap_cveval() + +begin + if (current > 0) { + ap = aps[current] + apaxis = AP_AXIS(ap) + + apid = AP_ID(ap) + apbeam = AP_BEAM(ap) + center = AP_CEN(ap, apaxis) + ap_cveval (AP_CV(ap), real (line)) + low = AP_LOW(ap, apaxis) + high = AP_HIGH(ap, apaxis) + } +end diff --git a/noao/twodspec/apextract/apvariance.x b/noao/twodspec/apextract/apvariance.x new file mode 100644 index 00000000..015eed74 --- /dev/null +++ b/noao/twodspec/apextract/apvariance.x @@ -0,0 +1,420 @@ +include <gset.h> +include "apertures.h" + + +# AP_VARIANCE -- Variance weighted extraction based on profile and CCD noise. +# If desired reject deviant pixels. In addition to the variance weighted +# spectrum, the unweighted and uncleaned "raw" spectrum is extracted and +# a sigma spectrum is returned. Wavelengths with saturated pixels are +# flagged with 0 value and negative sigma if cleaning. + +procedure ap_variance (im, ap, dbuf, nc, nl, c1, l1, sbuf, svar, profile, + nx, ny, xs, ys, spec, raw, specsig, nsubaps, asi) + +pointer im # IMIO pointer +pointer ap # Aperture structure +pointer dbuf # Data buffer +int nc, nl # Size of data buffer +int c1, l1 # Origin of data buffer +pointer sbuf # Sky values (NULL if none) +pointer svar # Sky variance +real profile[ny,nx] # Profile (returned) +int nx, ny # Size of profile array +int xs[ny], ys # Origin of profile array +real spec[ny,nsubaps] # Spectrum +real raw[ny,nsubaps] # Raw spectrum +real specsig[ny,nsubaps] # Sky variance in, spectrum sigma out +int nsubaps # Number of subapertures +pointer asi # Image interpolator for edge pixel weighting + +real rdnoise # Readout noise in RMS data numbers. +real gain # Gain in photons per data number. +real saturation # Maximum value for an unsaturated pixel. +bool clean # Clean cosmic rays? +real nclean # Number of pixels to clean +real lsigma, usigma # Rejection sigmas. + +bool sat +int fd, iterate, niterate, nrej, irej, nreject +int i, ix, iy, ix1, ix2 +real low, high, step, shift, x1, x2, wt1, wt2, s, w, dat, sk, var, var0 +real sum, wsum, wvsum, sum1, sum2, total1, total2 +real vmin, resid, rrej +pointer cv, gp +pointer sp, str, work, wt, xplot, yplot, eplot, fplot, data, sky, data1 + +real apgetr(), apgimr(), ap_cveval() +bool apgetb() +errchk apgimr, ap_asifit + +begin + # Get task parameters. + gain = apgimr ("gain", im) + rdnoise = apgimr ("readnoise", im) ** 2 + saturation = apgetr ("saturation") + if (!IS_INDEF(saturation)) + saturation = saturation * gain + clean = apgetb ("clean") + lsigma = apgetr ("lsigma") + usigma = apgetr ("usigma") + call ap_popen (gp, fd, "clean") + + # Allocate memory and one index. + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (work, 6*nx, TY_REAL) + wt = work - 1 + xplot = wt + nx + yplot = xplot + nx + eplot = yplot + nx + fplot = eplot + nx + data1 = fplot + nx + if (sbuf == NULL) { + call salloc (sky, nx, TY_REAL) + call aclrr (Memr[sky], nx) + sky = sky - 1 + var0 = rdnoise + } + + # Initialize + if (rdnoise == 0.) + vmin = 1. + else + vmin = rdnoise + if (clean) { + nclean = apgetr ("nclean") + if (nclean < 1.) + niterate = max (1., nclean * nx) + else + niterate = max (1., min (real (nx), nclean)) + } else + niterate = 0 + + call aclrr (spec, ny * nsubaps) + call aclrr (raw, ny * nsubaps) + call amovkr (-1., specsig, ny * nsubaps) + + i = AP_AXIS(ap) + low = AP_CEN(ap,i) + AP_LOW(ap,i) + high = AP_CEN(ap,i) + AP_HIGH(ap,i) + step = (high - low) / nsubaps + cv = AP_CV(ap) + + # For each line compute the weighted spectrum and then iterate + # to reject deviant pixels. Rejected pixels are flagged by negative + # variance. + + nreject = 0 + total1 = 0. + total2 = 0. + do iy = 1, ny { + shift = ap_cveval (cv, real (iy + ys - 1)) - c1 + 1 + x1 = max (0.5, low + shift) + c1 - xs[iy] + x2 = min (nc + 0.49, high + shift) + c1 - xs[iy] + if (x1 >= x2) + next + ix1 = nint (x1) + ix2 = nint (x2) + + call ap_asifit (dbuf+(iy+ys-1-l1)*nc, nc, xs[iy]-c1+1, + low+shift, high+shift, data, asi) +# data = dbuf + (iy + ys - 1 - l1) * nc + xs[iy] - c1 - 1 + if (sbuf != NULL) { + sky = sbuf + (iy - 1) * nx - 1 + var0 = rdnoise + Memr[svar+iy-1] + } + + # Set pixel weights for summing. +# if (asi != NULL) +# call asifit (asi, Memr[data], nc-xs[iy]+c1) + call ap_edge (asi, x1+1, x2+1, wt1, wt2) + + # First estimate spectrum by summing across the aperture. + # Accumulate the raw spectrum and set up various arrays for + # plotting and later access. + + sat = false + sum = 0. + wsum = 0. + wvsum = 0. + do ix = ix1, ix2 { + if (ix1 == ix2) + w = wt1 + else if (ix == ix1) + w = wt1 + else if (ix == ix2) + w = wt2 + else + w = 1. + dat = Memr[data+ix] + if (!IS_INDEF(saturation)) + if (dat > saturation) + sat = true + sk = Memr[sky+ix] + raw[iy,1] = raw[iy,1] + w * (dat - sk) + + Memr[xplot+ix] = ix + xs[iy] - 1 + Memr[yplot+ix] = dat - sk + Memr[data1+ix] = dat - sk + Memr[wt+ix] = w + var = max (vmin, var0 + max (0., dat)) + w = profile[iy,ix] / var + var = sqrt (var) + Memr[eplot+ix] = var + sum = sum + w * (dat - sk) + wsum = wsum + w * profile[iy,ix] + wvsum = wvsum + (w * var) ** 2 + } + if (wsum > 0.) { + spec[iy,1] = sum / wsum + specsig[iy,1] = sqrt (wvsum) / abs (wsum) + } else { + spec[iy,1] = 0. + specsig[iy,1] = -1. + } + + sum = 0. + wsum = 0. + wvsum = 0. + sum1 = 0. + sum2 = 0. + do ix = ix1, ix2 { + sum1 = sum1 + Memr[wt+ix] * Memr[data1+ix] + if (Memr[eplot+ix] <= 0.) + next + sk = Memr[sky+ix] + s = max (0., spec[iy,1]) * profile[iy,ix] + var = max (vmin, var0 + (s + sk)) + w = profile[iy,ix] / var + var = sqrt (var) + Memr[eplot+ix] = var + Memr[fplot+ix] = s + sum = sum + w * Memr[data1+ix] + wsum = wsum + w * profile[iy,ix] + wvsum = wvsum + (w * var) ** 2 + } + if (wsum > 0.) { + spec[iy,1] = sum / wsum + specsig[iy,1] = sqrt (wvsum) / abs (wsum) + sum2 = sum2 + spec[iy,1] + } else { + spec[iy,1] = 0. + specsig[iy,1] = -1. + sum1 = 0. + sum2 = 0. + } + + # Reject cosmic rays one at a time. + nrej = 0 + do iterate = 1, niterate { + irej = 0 + rrej = 0. + + # Compute revised variance estimate using profile model + # skip rejected pixels, find worst pixel. + + do ix = ix1, ix2 { + if (Memr[eplot+ix] <= 0.) + next + s = max (0., spec[iy,1]) * profile[iy,ix] + sk = Memr[sky+ix] + var = sqrt (max (vmin, var0 + max (0., s + sk))) + Memr[fplot+ix] = s + Memr[eplot+ix] = var + + resid = (Memr[data1+ix] - Memr[fplot+ix]) / var + if (abs (resid) > abs (rrej)) { + rrej = resid + irej = ix + } + } + + # Reject worst outlier. + + if (rrej <= -lsigma || rrej >= usigma) { + Memr[eplot+irej] = -Memr[eplot+irej] + Memr[data1+irej] = Memr[fplot+irej] + nrej = nrej + 1 + } else + break + + # Update spectrum estimate excluding rejected pixels. + sum = 0. + wsum = 0. + wvsum = 0. + sum1 = 0. + sum2 = 0. + do ix = ix1, ix2 { + sum1 = sum1 + Memr[wt+ix] * Memr[data1+ix] + if (Memr[eplot+ix] <= 0.) + next + w = profile[iy,ix] / Memr[eplot+ix]**2 + sum = sum + w * Memr[data1+ix] + wsum = wsum + w * profile[iy,ix] + wvsum = wvsum + (w * Memr[eplot+ix]) ** 2 + } + + if (wsum > 0.) { + spec[iy,1] = sum / wsum + specsig[iy,1] = sqrt (wvsum) / abs (wsum) + sum2 = sum2 + spec[iy,1] + } else { + spec[iy,1] = 0. + specsig[iy,1] = -1. + sum1 = 0. + sum2 = 0. + } + } + + nreject = nreject + nrej + total1 = total1 + sum1 + total2 = total2 + sum2 + + # Calculate subapertures if desired. + if (nsubaps > 1) { + do i = 1, nsubaps { + x1 = max (0.5, low + (i - 1) * step + shift) + c1 - xs[iy] + x2 = min (nc + 0.49, low + i * step + shift) + c1 - xs[iy] + if (x1 >= x2) { + spec[iy,i] = 0. + raw[iy,i] = 0. + specsig[iy,i] = -1. + next + } + ix1 = nint (x1) + ix2 = nint (x2) + call ap_edge (asi, x1+1, x2+1, wt1, wt2) + + sum = 0. + wvsum = 0. + raw[iy,i] = 0. + do ix = ix1, ix2 { + if (ix1 == ix2) + w = wt1 + else if (ix == ix1) + w = wt1 + else if (ix == ix2) + w = wt2 + else + w = 1. + raw[iy,i] = raw[iy,i] + w * Memr[yplot+ix] + if (Memr[eplot+ix] <= 0.) + next + w = profile[iy,ix] / Memr[eplot+ix]**2 + sum = sum + w * Memr[data1+ix] + wvsum = wvsum + (w * Memr[eplot+ix]) ** 2 + } + + if (wsum > 0.) { + spec[iy,i] = sum / wsum + specsig[iy,i] = sqrt (wvsum) / abs (wsum) + } else { + spec[iy,i] = 0. + specsig[iy,i] = -1. + } + } + } + + # Flag points with saturated pixels. + if (sat) + do i = 1, nsubaps + specsig[iy,i] = -specsig[iy,i] + + # Plot profile with cosmic rays if desired. + if (gp != NULL && nrej > 0 && spec[iy,1] > 0.) { + call sprintf (Memc[str], SZ_LINE, "Profile %4d") + call pargi (iy) + s = Memr[yplot+ix1] - abs (Memr[eplot+ix1]) + w = Memr[yplot+ix1] + abs (Memr[eplot+ix1]) + do ix = ix1+1, ix2 { + s = min (s, Memr[yplot+ix] - abs (Memr[eplot+ix])) + w = max (w, Memr[yplot+ix] + abs (Memr[eplot+ix])) + } + sum = w - s + x1 = ix1 + xs[iy] - 2 + x2 = ix2 + xs[iy] + s = s - 0.1 * sum + w = w + 0.1 * sum + call gclear (gp) + call gswind (gp, x1, x2, s, w) + call glabax (gp, Memc[str], "", "") + + do ix = ix1, ix2 { + if (Memr[eplot+ix] > 0.) { + call gmark (gp, Memr[xplot+ix], Memr[yplot+ix], + GM_PLUS, 2., 2.) + call gmark (gp, Memr[xplot+ix], Memr[yplot+ix], + GM_VEBAR, 2., -6.*Memr[eplot+ix]) + } else { + call gmark (gp, Memr[xplot+ix], Memr[yplot+ix], + GM_CROSS, 2., 2.) + call gmark (gp, Memr[xplot+ix], Memr[yplot+ix], + GM_VEBAR, 1., 6.*Memr[eplot+ix]) + } + } + call gpline (gp, Memr[xplot+ix1], Memr[fplot+ix1], ix2-ix1+1) + } + } + + # To avoid any bias, scale weighted extraction to same total flux + # as raw spectrum (with rejected pixels replaced by fit). + + if (total1 * total2 <= 0.) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT: WARNING - Aperture %d:") + call pargi (AP_ID(ap)) + call ap_log (Memc[str], YES, NO, YES) + call sprintf (Memc[str], SZ_LINE, + " Total variance weighted spectrum flux is %g") + call pargr (total2) + call ap_log (Memc[str], YES, NO, YES) + call sprintf (Memc[str], SZ_LINE, + " Total unweighted spectrum flux is %g") + call pargr (total1) + call ap_log (Memc[str], YES, NO, YES) + call sprintf (Memc[str], SZ_LINE, + " Variance spectrum bias factor ignored") + call ap_log (Memc[str], YES, NO, YES) + } else { + sum = total1 / total2 + call amulkr (spec, sum, spec, ny * nsubaps) + call amulkr (specsig, sum, specsig, ny * nsubaps) + if (sum < .5 || sum > 2) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT: WARNING - Aperture %d:") + call pargi (AP_ID(ap)) + call ap_log (Memc[str], YES, NO, YES) + call sprintf (Memc[str], SZ_LINE, + " Total variance weighted spectrum flux is %g") + call pargr (total2) + call ap_log (Memc[str], YES, NO, YES) + call sprintf (Memc[str], SZ_LINE, + " Total unweighted spectrum flux is %g") + call pargr (total1) + call ap_log (Memc[str], YES, NO, YES) + call sprintf (Memc[str], SZ_LINE, + "EXTRACT: Aperture %d variance spectrum bias factor is %g") + call pargi (AP_ID(ap)) + call pargr (total1 / total2) + call ap_log (Memc[str], YES, NO, YES) + } else { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT: Aperture %d variance spectrum bias factor is %g") + call pargi (AP_ID(ap)) + call pargr (total1 / total2) + call ap_log (Memc[str], YES, NO, NO) + } + } + + # Log the number of rejected pixels. + if (clean) { + call sprintf (Memc[str], SZ_LINE, + "EXTRACT: %d pixels rejected from aperture %d") + call pargi (nreject) + call pargi (AP_ID(ap)) + call ap_log (Memc[str], YES, NO, NO) + } + + call ap_pclose (gp, fd) + call sfree (sp) +end diff --git a/noao/twodspec/apextract/apwidth.cl b/noao/twodspec/apextract/apwidth.cl new file mode 100644 index 00000000..94a247d7 --- /dev/null +++ b/noao/twodspec/apextract/apwidth.cl @@ -0,0 +1,59 @@ +# APWIDTH -- Script to report widths from APALL database files. +# The input is the image name and database directory. +# The output is image name, aperture number, x center, y center, and width. +# +# To install this script copy it to a directory, such as your IRAF login +# directory "home$" in this example. Define the task in your loginuser.cl +# or login.cl with +# +# task apwidth = home$apwidth.cl +# +# Note that you can substitute some other path to the script if desired. + +procedure apwidth (image) + +file image {prompt="Image name"} +file database = "database" {prompt="Database"} + +begin + file dbfile + string im + int ap, axis + real xc, yc, aplow1, aphigh1, aplow2, aphigh2, width + + # Form database name from the database and image names. + dbfile = database // "/ap" // image + + # Check that the database file actually exists. + if (!access(dbfile)) + error (1, "Databse file not found (" // dbfile // ")") + + # Loop through each line of the database file. Extract information + # and print the output line when the axis keyword is found. This + # assumes the aperture limits are read before the axis. + + axis = INDEF + list = dbfile + while (fscan (list, line) != EOF) { + if (fscan (line, s1) < 1) + next + if (s1 == "begin") + i = fscan (line, s1, s1, im, ap, xc, yc) + else if (s1 == "low") + i = fscan (line, s1, aplow1, aplow2) + else if (s1 == "high") + i = fscan (line, s1, aphigh1, aphigh2) + else if (s1 == "axis") + i = fscan (line, s1, axis) + + if (axis != INDEF) { + if (axis == 1) + width = aphigh1 - aplow1 + else + width = aphigh2 - aplow2 + printf ("%s %2d %8.4g %8.4g %8.4g\n", im, ap, xc, yc, width) + axis = INDEF + } + } + list = "" +end diff --git a/noao/twodspec/apextract/apylevel.x b/noao/twodspec/apextract/apylevel.x new file mode 100644 index 00000000..aa208453 --- /dev/null +++ b/noao/twodspec/apextract/apylevel.x @@ -0,0 +1,103 @@ +# AP_YLEVEL -- Set the aperture to intercept the specified y level. + +procedure ap_ylevel (imdata, npts, ylevel, peak, bkg, grow, center, low, high) + +real imdata[npts] # Image data +int npts # Number of image points +real ylevel # Y value +bool peak # Is y a fraction of peak? +bool bkg # Subtract a background? +real grow # Grow factor +real center # Center of aperture +real low, high # Equal flux points + +int i1, i2, j1, j2, k1, k2 +real y, y1, y2, a, b, ycut, x + +begin + if ((center < 1.) || (center >= npts) || IS_INDEF (ylevel)) + return + + if (bkg) { + i1 = nint (center) + i2 = max (1, nint (center + low)) + for (k1=i1; k1 > i2 && imdata[k1] <= imdata[k1-1]; k1=k1-1) + ; + for (; k1 > i2 && imdata[k1] >= imdata[k1-1]; k1=k1-1) + ; + + i2 = min (npts, nint (center + high)) + for (k2=i1; k2 < i2 && imdata[k2] <= imdata[k2+1]; k2=k2+1) + ; + for (; k2 < i2 && imdata[k2] >= imdata[k2+1]; k2=k2+1) + ; + + a = imdata[k1] + b = (imdata[k2] - imdata[k1]) / (k2 - k1) + } else { + k1 = center + a = 0. + b = 0. + } + + i1 = center + i2 = i1 + 1 + y1 = imdata[i1] - a - b * (i1 - k1) + y2 = imdata[i2] - a - b * (i2 - k1) + y = y1 * (i2 - center) + y2 * (center - i1) + + if (peak) + ycut = ylevel * y + else + ycut = ylevel + + if (y > ycut) { + for (j1 = i1; j1 >= 1; j1 = j1 - 1) { + y1 = imdata[j1] - a - b * (j1 - k1) + if (y1 <= ycut) + break + } + if (j1 >= 1) { + j2 = j1 + 1 + y2 = imdata[j2] - a - b * (j2 - k1) + x = (ycut + y2 * j1 - y1 * j2) / (y2 - y1) - center + low = max (low, (1.+grow)*x) + } + + for (j2 = i2; j2 <= npts; j2 = j2 + 1) { + y2 = imdata[j2] - a - b * (j2 - k1) + if (y2 <= ycut) + break + } + if (j2 <= npts) { + j1 = j2 - 1 + y1 = imdata[j1] - a - b * (j1 - k1) + x = (ycut + y2*j1 - y1*j2) / (y2 - y1) - center + high = min (high, (1.+grow)*x) + } + } else { + for (j1 = i1; j1 >= 1; j1 = j1 - 1) { + y1 = imdata[j1] - a - b * (j1 - k1) + if (y1 >= ycut) + break + } + if (j1 >= 1) { + j2 = j1 + 1 + y2 = imdata[j2] - a - b * (j2 - k1) + x = (ycut + y2 * j1 - y1 * j2) / (y2 - y1) - center + low = max (low, (1.+grow)*x) + } + + for (j2 = i2; j2 <= npts; j2 = j2 + 1) { + y2 = imdata[j2] - a - b * (j2 - k1) + if (y2 >= ycut) + break + } + if (j2 <= npts) { + j1 = j2 - 1 + y1 = imdata[j1] - a - b * (j1 - k1) + x = (ycut + y2*j1 - y1*j2) / (y2 - y1) - center + high = min (high, (1.+grow)*x) + } + } +end diff --git a/noao/twodspec/apextract/doc/apall.hlp b/noao/twodspec/apextract/doc/apall.hlp new file mode 100644 index 00000000..c4e50072 --- /dev/null +++ b/noao/twodspec/apextract/doc/apall.hlp @@ -0,0 +1,557 @@ +.help apall Sep96 noao.twodspec.apextract +.ih +NAME +apall -- Extract one dimensional sums across the apertures +.ih +USAGE +apall input +.ih +PARAMETERS +.ls input +List of input images. +.le +.ls output = "" +List of output root names for extracted spectra. If the null +string is given or the end of the output list is reached before the end +of the input list then the input image name is used as the output root name. +This will not conflict with the input image since an aperture number +extension is added for onedspec format, the extension ".ms" for multispec +format, or the extension ".ec" for echelle format. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls format = "multispec" (onedspec|multispec|echelle|strip) +Format for output extracted spectra. "Onedspec" format extracts each +aperture to a separate image while "multispec" and "echelle" extract +multiple apertures for the same image to a single output image. +The "multispec" and "echelle" format selections differ only in the +extension added. The "strip" format produces a separate 2D image in +which each column or line along the dispersion axis is shifted to +exactly align the aperture based on the trace information. +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +Input images without/with a database entry are skipped silently. +.le +.ls profiles = "" +List of profile images for variance weighting or cleanning. If variance +weighting or cleanning a profile of each aperture is computed from the +input image unless a profile image is specified, in which case the +profile is computed from the profile image. The profile image must +have the same dimensions and dispersion and it is assumed that the +spectra have the same position and profile shape as in the object +spectra. Use of a profile image is generally not required even for +faint input spectra but the option is available for those who wish +to use it. +.le + +.ce +PROCESSING PARAMETERS +.ls interactive = yes +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing, trace +fitting, and extraction review are disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = yes +Recenter the apertures? +.le +.ls resize = yes +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace the apertures? +.le +.ls fittrace = yes +Interactively fit the traced positions by a function? The \fIinteractive\fR +parameter must also be yes. +.le +.ls extract = yes +Extract the one dimensional aperture sums? +.le +.ls extras = yes +Extract the raw spectrum (if variance weighting is used), the sky spectrum +(if background subtraction is used), and sigma spectrum (if variance +weighting is used)? This information is extracted to the third dimension +of the output image. +.le +.ls review = yes +Review the extracted spectra? The \fIinteractive\fR parameter must also be +yes. +.le + +.ls line = INDEF, nsum = 10 +The dispersion line (line or column perpendicular to the dispersion +axis) and number of adjacent lines (half before and half after unless +at the end of the image) used in finding, recentering, resizing, +and editing operations. A line of INDEF selects the middle of the +image along the dispersion axis. A positive nsum selects a sum of +lines and a negative selects a median of lines. +.le + +.ce +DEFAULT APERTURE PARAMETERS +.ls lower = -5., upper = 5. +Default lower and upper aperture limits relative to the aperture center. +These limits are used for apertures found with \fBapfind\fR and when +defining the first aperture in \fBapedit\fR. +.le +.ls apidtable = "" +Aperture identification table. This may be either a text file or an +image. A text file consisting of lines with an aperture number, beam +number, and aperture title or identification. An image will contain the +keywords SLFIBnnn with string value consisting of aperture number, beam +number, optional right ascension and declination, and aperture title. This +information is used to assign aperture information automatically in +\fBapfind\fR and \fBapedit\fR. +.le + +.ce +DEFAULT BACKGROUND PARAMETERS +.ls b_function = "chebyshev" +Default background fitting function. The fitting function types are +"chebyshev" polynomial, "legendre" polynomial, "spline1" linear spline, and +"spline3" cubic spline. +.le +.ls b_order = 1 +Default background function order. The order refers to the number of +terms in the polynomial functions or the number of spline pieces in the spline +functions. +.le +.ls b_sample = "-10:-6,6:10" +Default background sample. The sample is given by a set of colon separated +ranges each separated by either whitespace or commas. The string "*" refers +to all points. Note that the background coordinates are relative to the +aperture center and not image pixel coordinates so the endpoints need not +be integer. +.le +.ls b_naverage = -3 +Default number of points to average or median. Positive numbers +average that number of sequential points to form a fitting point. +Negative numbers median that number, in absolute value, of sequential +points. A value of 1 does no averaging and each data point is used in the +fit. +.le +.ls b_niterate = 0 +Default number of rejection iterations. If greater than zero the fit is +used to detect deviant fitting points and reject them before repeating the +fit. The number of iterations of this process is given by this parameter. +.le +.ls b_low_reject = 3., b_high_reject = 3. +Default background lower and upper rejection sigmas. If greater than zero +points deviating from the fit below and above the fit by more than this +number of times the sigma of the residuals are rejected before refitting. +.le +.ls b_grow = 0. +Default reject growing radius. Points within a distance given by this +parameter of any rejected point are also rejected. +.le + +.ce +APERTURE CENTERING PARAMETERS +.ls width = 5. +Width of spectrum profiles. This parameter is used for the profile +centering algorithm in this and other tasks. +.le +.ls radius = 10. +The profile centering error radius for the centering algorithm. +.le +.ls threshold = 0. +Centering threshold for the centering algorithm. The range of pixel intensities +near the initial centering position must exceed this threshold. +.le + +.ce +AUTOMATIC FINDING AND ORDERING PARAMETERS +.ls nfind +Maximum number of apertures to be defined. This is a query parameter +so the user is queried for a value except when given explicitly on +the command line. +.le +.ls minsep = 5. +Minimum separation between spectra. Weaker spectra or noise within this +distance of a stronger spectrum are rejected. +.le +.ls maxsep = 1000. +Maximum separation between adjacent spectra. This parameter +is used to identify missing spectra in uniformly spaced spectra produced +by fiber spectrographs. If two adjacent spectra exceed this separation +then it is assumed that a spectrum is missing and the aperture identification +assignments will be adjusted accordingly. +.le +.ls order = "increasing" +When assigning aperture identifications order the spectra "increasing" +or "decreasing" with increasing pixel position (left-to-right or +right-to-left in a cross-section plot of the image). +.le + +.ce +RECENTERING PARAMETERS +.ls aprecenter = "" +List of apertures to be used in shift calculation. +.le +.ls npeaks = INDEF +Select the specified number of apertures with the highest peak values +to be recentered. If the number is INDEF all apertures will be selected. +If the value is less than 1 then the value is interpreted as a fraction +of total number of apertures. +.le +.ls shift = yes +Use the average shift from recentering the apertures selected by the +\fIaprecenter\fR parameter to apply to the apertures selected by the +\fIapertures\fR parameter. The recentering is then a constant shift for +all apertures. +.le + +.ce +RESIZING PARAMETERS +.ls llimit = INDEF, ulimit = INDEF +Lower and upper aperture size limits. If the parameter \fIylevel\fR is +INDEF then these limits are assigned to all apertures. Otherwise +these parameters are used as limits to the resizing operation. +A value of INDEF places the aperture limits at the image edge (for the +dispersion line used). +.le +.ls ylevel = 0.1 +Data level at which to set aperture limits. If it is INDEF then the +aperture limits are set at the values given by the parameters +\fIllimit\fR and \fIulimit\fR. If it is not INDEF then it is a +fraction of the peak or an actual data level depending on the parameter +\fIpeak\fR. It may be relative to a local background or to zero +depending on the parameter \fIbkg\fR. +.le +.ls peak = yes +Is the data level specified by \fIylevel\fR a fraction of the peak? +.le +.ls bkg = yes +Subtract a simple background when interpreting the \fBylevel\fR parameter. +The background is a slope connecting the first inflection points +away from the aperture center. +.le +.ls r_grow = 0. +Change the lower and upper aperture limits by this fractional amount. +The factor is multiplied by each limit and the result added to limit. +.le +.ls avglimits = no +Apply the average lower and upper aperture limits to all apertures. +.le + +.ce +TRACING PARAMETERS +.ls t_nsum = 10 +Number of dispersion lines to be summed at each step along the dispersion. +.le +.ls t_step = 10 +Step along the dispersion axis between determination of the spectrum +positions. +.le +.ls t_nlost = 3 +Number of consecutive steps in which the profile is lost before quitting +the tracing in one direction. To force tracing to continue through +regions of very low signal this parameter can be made large. Note, +however, that noise may drag the trace away before it recovers. +.le +.ls t_function = "legendre" +Default trace fitting function. The fitting function types are +"chebyshev" polynomial, "legendre" polynomial, "spline1" linear spline, and +"spline3" cubic spline. +.le +.ls t_order = 2 +Default trace function order. The order refers to the number of +terms in the polynomial functions or the number of spline pieces in the spline +functions. +.le +.ls t_sample = "*" +Default fitting sample. The sample is given by a set of colon separated +ranges each separated by either whitespace or commas. The string "*" refers +to all points. +.le +.ls t_naverage = 1 +Default number of points to average or median. Positive numbers +average that number of sequential points to form a fitting point. +Negative numbers median that number, in absolute value, of sequential +points. A value of 1 does no averaging and each data point is used in the +.le +.ls t_niterate = 0 +Default number of rejection iterations. If greater than zero the fit is +used to detect deviant traced positions and reject them before repeating the +fit. The number of iterations of this process is given by this parameter. +.le +.ls t_low_reject = 3., t_high_reject = 3. +Default lower and upper rejection sigma. If greater than zero traced +points deviating from the fit below and above the fit by more than this +number of times the sigma of the residuals are rejected before refitting. +.le +.ls t_grow = 0. +Default reject growing radius. Traced points within a distance given by this +parameter of any rejected point are also rejected. +.le + +.ce +EXTRACTION PARAMETERS +.ls background = "none" (none|average|median|minimum|fit) +Type of background subtraction. The choices are "none" for no background +subtraction, "average" to average the background within the background +regions, "median" to use the median in the background regions, "minimum" to +use the minimum in the background regions, or "fit" to fit across the +dispersion using the background within the background regions. Note that +the "average" option does not do any medianing or bad pixel checking, +something which is recommended. The fitting option is slower than the +other options and requires additional fitting parameter. +.le +.ls skybox = 1 +Box car smoothing length for sky background when using background +subtraction. Since the background noise is often the limiting factor +for good extraction one may box car smooth the sky to improve the +statistics in smooth background regions at the expense of distorting +the subtraction near spectral features. This is most appropriate when +the sky regions are limited due to a small slit length. +.le +.ls weights = "none" (none|variance) +Type of extraction weighting. Note that if the \fIclean\fR parameter is +set then the weights used are "variance" regardless of the weights +specified by this parameter. The choices are: +.ls "none" +The pixels are summed without weights except for partial pixels at the +ends. +.le +.ls "variance" +The extraction is weighted by the variance based on the data values +and a poisson/ccd model using the \fIgain\fR and \fIreadnoise\fR +parameters. +.le +.le +.ls pfit = "fit1d" (fit1d|fit2d) +Profile fitting algorithm to use with variance weighting or cleaning. +When determining a profile the two dimensional spectrum is divided by +an estimate of the one dimensional spectrum to form a normalized two +dimensional spectrum profile. This profile is then smoothed by fitting +one dimensional functions, "fit1d", along the lines or columns most closely +corresponding to the dispersion axis or a special two dimensional +function, "fit2d", described by Marsh (see \fBapprofile\fR). +.le +.ls clean = no +Detect and replace deviant pixels? +.le +.ls saturation = INDEF +Saturation or nonlinearity level in data units. During variance weighted +extractions wavelength points having any pixels above this value are +excluded from the profile determination and the sigma spectrum extraction +output, if selected by the \fIextras\fR parameter, flags wavelengths with +saturated pixels with a negative sigma. +.le +.ls readnoise = 0. +Read out noise in photons. This parameter defines the minimum noise +sigma. It is defined in terms of photons (or electrons) and scales +to the data values through the gain parameter. A image header keyword +(case insensitive) may be specified to get the value from the image. +.le +.ls gain = 1 +Detector gain or conversion factor between photons/electrons and +data values. It is specified as the number of photons per data value. +A image header keyword (case insensitive) may be specified to get the value +from the image. +.le +.ls lsigma = 4., usigma = 4. +Lower and upper rejection thresholds, given as a number of times the +estimated sigma of a pixel, for cleaning. +.le +.ls nsubaps = 1 +During extraction it is possible to equally divide the apertures into +this number of subapertures. For multispec format all subapertures will +be in the same file with aperture numbers of 1000*(subap-1)+ap where +subap is the subaperture (1 to nsubaps) and ap is the main aperture +number. For echelle format there will be a separate echelle format +image containing the same subaperture from each order. The name +will have the subaperture number appended. For onedspec format +each subaperture will be in a separate file with extensions and +aperture numbers as in the multispec format. +.le +.ih +ADDITIONAL PARAMETERS +Dispersion axis and I/O parameters are taken from the package parameters. +.ih +DESCRIPTION +This task provides functions for defining, modifying, tracing, and +extracting apertures from two dimensional spectra. The functions +desired are selected using switch parameters. When the task is +run interactively queries are made at each step allowing additional +control of the operations performed on each input image. + +The functions, in the order in which they are generally performed, are +summarized below. +.ls o +Automatically find a specified number of spectra and assign default +apertures. Apertures may also be inherited from another image or +defined using an interactive graphical interface called the \fIaperture +editor\fR. +.le +.ls o +Recenter selected reference apertures on the image spectrum profiles. +.le +.ls o +Resize the selected reference apertures based on spectrum profile width. +.le +.ls o +Interactively define or adjust aperture definitions using a graphical +interface called the \fIaperture editor\fR. All function may also +be performed from this editor and, so, provides an alternative +method of processing and extracting spectra. +.le +.ls o +Trace the positions of the selected spectra profiles from a starting image line +or column to other image lines or columns and fit a smooth function. +The trace function is used to shift the center of the apertures +at each dispersion point in the image. +.le +.ls o +Extract the flux in the selected apertures into one dimensional spectra in +various formats. This includes possible background subtraction, variance +weighting, and bad pixel rejection. +.le + +Each of these functions has different options and parameters. In +addition to selecting any of these functions in this task, they may +also be selected using the aperture editor and as individual +commands (which themselves allow selection of other functions). When +broken down into individual tasks the parameters are also sorted by +their function though there are then some mutual parameter +interdependencies. This functional decomposition is what was available +prior to the addition of the \fBapall\fR task. It is recommended that +this task be used because it collects all the parameters in one +place eliminating confusion over where a particular parameter +is defined. However, documenting the various functions +is better organized in terms of the separate descriptions given for +each of the functions; namely under the help topics +\fBapdefault, apfind, aprecenter, apresize, apedit, +aptrace\fR, and \fBapsum\fR. +.ih +EXAMPLES +1. This example may be executed if desired. First we create an artificial +spectrum with four spectra and a background. After it is created you +can display or plot it. Next we define the dispersion axis and set the +verbose flag to better illustrate what is happening. The task APALL +is run with the default parameters except for background fitting and +subtracting added. The text beginning with # are comments of things to +try and do. + +.nf + ap> artdata + ar> unlearn artdata + ar> mk1dspec apdemo1d nl=50 + ar> mk2dspec apdemo2d model=STDIN + apdemo1d 1. gauss 3 0 20 .01 + apdemo1d .8 gauss 3 0 40 .01 + apdemo1d .6 gauss 3 0 60 .01 + apdemo1d .4 gauss 3 0 80 .01 + [EOF=Control D or Control Z] + ar> mknoise apdemo2d background=100. rdnoise=3. poisson+ + ar> bye + # Display or plot the spectrum + ap> dispaxis=2; verbose=yes + ap> unlearn apall + ap> apall apdemo2d back=fit + Searching aperture database ... + Find apertures for apdemo2d? (yes): + Finding apertures ... + Number of apertures to be found automatically (1): 4 + Jul 31 16:55: FIND - 4 apertures found for apdemo2d. + Resize apertures for apdemo2d? (yes): + Resizing apertures ... + Jul 31 16:55: RESIZE - 4 apertures resized for apdemo2d. + Edit apertures for apdemo2d? (yes): + # Get a list of commands with '?' + # See all the parameters settings with :par + # Try deleting and marking a spectrum with 'd' and 'm' + # Look at the background fitting parameters with 'b' (exit with 'q') + # Exit with 'q' + Trace apertures for apdemo2d? (yes): + Fit traced positions for apdemo2d interactively? (yes): + Tracing apertures ... + Fit curve to aperture 1 of apdemo2d interactively (yes): + # You can use ICFIT commands to adjust the fit. + Fit curve to aperture 2 of apdemo2d interactively (yes): n + Fit curve to aperture 3 of apdemo2d interactively (no): + Fit curve to aperture 4 of apdemo2d interactively (no): y + Jul 31 16:56: TRACE - 4 apertures traced in apdemo2d. + Write apertures for apdemo2d to apdemosdb (yes): + Jul 31 16:56: DATABASE - 4 apertures for apdemo2d written to database. + Extract aperture spectra for apdemo2d? (yes): + Review extracted spectra from apdemo2d? (yes): + Extracting apertures ... + Review extracted spectrum for aperture 1 from apdemo2d? (yes): + # Type 'q' to quit + Jul 31 16:56: EXTRACT - Aperture 1 from apdemo2d --> apdemo2d.ms + Review extracted spectrum for aperture 2 from apdemo2d? (yes): N + Jul 31 16:56: EXTRACT - Aperture 2 from apdemo2d --> apdemo2d.ms + Jul 31 16:56: EXTRACT - Aperture 3 from apdemo2d --> apdemo2d.ms + Jul 31 16:57: EXTRACT - Aperture 4 from apdemo2d --> apdemo2d.ms +.fi + +2. To extract a series of similar spectra noninteractively using a +reference for the aperture definitions, then recentering and resizing +but not retracing: + +.nf + ap> apall fib*.imh ref=flat inter- trace- +.fi + +Note that the interactive flag automatically turns off the edit, fittrace, +and review options and the reference image eliminates the find +(find only occurs if there are no initial apertures). +.ih +REVISIONS +.ls APALL V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". + +The aperture ID table information may now be contained in the +image header under the keywords SLFIBnnn. + +The "nsubaps" parameter now allows onedspec and echelle output formats. +The echelle format is appropriate for treating each subaperture as +a full echelle extraction. +.le +.ls APALL V2.10.3 +The dispersion axis parameter was moved to purely a package parameter. + +As a final step when computing a weighted/cleaned spectrum the total +fluxes from the weighted spectrum and the simple unweighted spectrum +(excluding any deviant and saturated pixels) are computed and a +"bias" factor of the ratio of the two fluxes is multiplied into +the weighted spectrum and the sigma estimate. This makes the total +fluxes the same. In this version the bias factor is recorded in the logfile +if one is kept. Also a check is made for unusual bias factors. +If the two fluxes disagree by more than a factor of two a warning +is given on the standard output and the logfile with the individual +total fluxes as well as the bias factor. If the bias factor is +negative a warning is also given and no bias factor is applied. +In the previous version a negative (inverted) spectrum would result. +.le +.ih +SEE ALSO +apdefault, apfind, aprecenter, apresize, apedit, aptrace, apsum +.endhelp diff --git a/noao/twodspec/apextract/doc/apbackground.hlp b/noao/twodspec/apextract/doc/apbackground.hlp new file mode 100644 index 00000000..93a49e42 --- /dev/null +++ b/noao/twodspec/apextract/doc/apbackground.hlp @@ -0,0 +1,79 @@ +.help apbackground Aug90 noao.twodspec.apextract + +.ce +Background Determination + + +Data from slit spectra allow the determination and subtraction +of the background sky using information from regions near the object +of interest. Background subtraction may also apply to cases of +scattered light though other techniques for scattered light removal +may be more appropriate. The APEXTRACT package provides for determining +the background level at each wavelength (line or column along the dispersion +axis) from a set of regions and extrapolating and subtracting the +background at each pixel extracted from the object profile. The +type of background used during extraction is specified by the parameter +\fIbackground\fR. If the value "none" is used then no background is +subtracted and any background parameters defined for an aperture are +ignored. If the value is "average", "median", "minimum" or "fit" then a +background is determined, including a variance estimate when using variance +weighted extraction (see \fIapvariance\fR), and the subtracted background +spectrum may be output if the \fIextras\fR parameter is set. + +The basic aperture definition structure used in the APEXTRACT package +includes associated background regions and fitting parameters. The +background regions are specified by a list of colon delimited ranges +defined relative to the center of the aperture. There are generally +two ranges, one on each side of the object, though one sided or more +complex sets may be used to avoid contaminated or missing parts +of the slit. The default ranges are defined by the parameter +\fIb_sample\fR. Often the ranges are better set graphically using a +cursor by invoking the 'b' option of the aperture editor. + +If the background type is "average", "median", or "minimum" then pixels +occupying these regions are averaged, medianed, or the minimum found to +produce a single background level for all object pixels at each wavelength. +Note that the "average" choice does not exclude any pixels which may +yield a background contaminated by cosmic rays. The "median" or "minimum" +is recommended instead. + +If the background type is "fit" then a function is fit to the pixels in the +background regions using the ICFIT options (see \fBicfit\fR). The +parameter \fIb_naverage\fR may be used to compute averages or medians of +groups or all of the points within each sample region. The fit is defined +by a function type \fIb_function\fR; one of legendre polynomial, chebyshev +polynomial, linear spline, or cubic spline, and function order +\fIb_order\fR (number of polynomial terms or spline pieces). An +interactive rejection of grossly deviant points from the fit may also be +used. The fitted function can define a constant, sloped, or higher order +background for the object pixels. + +Note that the background setting function, the 'b' key in \fBapedit\fR, +may be used to set the background regions for all the background options +but it will always show the result of a fit regardless of the background +type. + +After determining a background by averaging, medianing, minimizing, or +fitting, a box car smoothing step may be applied. The box car size is +given by the parameter \fIskybox\fR. When the number of available +background pixels is small, due to a small slit for instance, the noise +introduced to the extracted object spectrum may be unsatisfactorily large. +By smoothing the background one can reduce the noise when the background +consists of a smooth continuum. The trade-off, however, is that near sharp +features the smoothing will smear the features out and give a poorer +subtraction of these features. One could extract both the object and +background separately and apply a background smoothing separately using +other image processing tools. However, this is not possible for variance +weighted extraction because of the intimate connection between the +background levels, the profile determination, and the variance estimates +based on both. Thus, this smoothing feature is included. + +The background determined by the methods outlined above is actually +subtracted as a separate step during extraction. The background +is also used during profile fitting when cleaning or using variance +weighted extraction. See \fBapvariance\fR and \fBapprofile\fR for +further discussion. +.ih +SEE ALSO +approfile apvariance apdefault icfit apall apsum +.endhelp diff --git a/noao/twodspec/apextract/doc/apdefault.hlp b/noao/twodspec/apextract/doc/apdefault.hlp new file mode 100644 index 00000000..e17fe50d --- /dev/null +++ b/noao/twodspec/apextract/doc/apdefault.hlp @@ -0,0 +1,95 @@ +.help apdefault Jul95 noao.twodspec.apextract +.ih +NAME +apdefault -- Set default aperture parameters for the package +.ih +USAGE +apdefault +.ih +PARAMETERS +.ls lower = -5., upper = 5. +Default lower and upper aperture limits relative to the aperture center. +These limits are used for apertures found with \fBapfind\fR and when +defining the first aperture in \fBapedit\fR. +.le +.ls apidtable = "" +Aperture identification table. This may be either a text file or an +image. A text file consisting of lines with an aperture number, beam +number, and aperture title or identification. An image will contain the +keywords SLFIBnnn with string value consisting of aperture number, beam +number, optional right ascension and declination, and aperture title. This +information is used to assign aperture information automatically in +\fBapfind\fR and \fBapedit\fR. +.le + +.ce +Default Background Subtraction Parameters +.ls b_function = "chebyshev" +Default background fitting function. The fitting function types are +"chebyshev" polynomial, "legendre" polynomial, "spline1" linear spline, and +"spline3" cubic spline. +.le +.ls b_order = 1 +Default background function order. The order refers to the number of +terms in the polynomial functions or the number of spline pieces in the spline +functions. +.le +.ls b_sample = "-10:-6,6:10" +Default background sample. The sample is given by a set of colon separated +ranges each separated by either whitespace or commas. The string "*" refers +to all points. Note that the background coordinates are relative to the +aperture center and not image pixel coordinates so the endpoints need not +be integer. +.le +.ls b_naverage = -3 +Default number of points to average or median. Positive numbers +average that number of sequential points to form a fitting point. +Negative numbers median that number, in absolute value, of sequential +points. A value of 1 does no averaging and each data point is used in the +fit. +.le +.ls b_niterate = 0 +Default number of rejection iterations. If greater than zero the fit is +used to detect deviant fitting points and reject them before repeating the +fit. The number of iterations of this process is given by this parameter. +.le +.ls b_low_reject = 3., b_high_reject = 3. +Default background lower and upper rejection sigmas. If greater than zero +points deviating from the fit below and above the fit by more than this +number of times the sigma of the residuals are rejected before refitting. +.le +.ls b_grow = 0. +Default reject growing radius. Points within a distance given by this +parameter of any rejected point are also rejected. +.le +.ih +DESCRIPTION +This task sets the values of the default aperture parameters for the +tasks \fBapedit\fR and \fBapfind\fR which define new apertures. For a +description of the components of an aperture see the paper \fBThe +APEXTRACT Package\fR. In \fBapedit\fR the default aperture limits and +background parameters are only used if there are no other +apertures defined. The aperture identification table is used when +reordering the apertures with the 'o' key. When run the parameters are +displayed and modified using the \fBeparam\fR task. + +The aperture limits and background fitting sample regions are defined +relative to the center of the aperture. The background fitting parameters +are those used by the ICFIT package. They may be modified interactively +with the 'b' key in the task \fBapedit\fR. For more on background fitting +and subtracting see \fBapbackground\fR. +.ih +EXAMPLES +To review and modify the default aperture parameters: + + cl> apdefault +.ih +.ih +REVISIONS +.ls APDEFAULT V2.11 +The aperture ID table information may now be contained in the +image header under the keywords SLFIBnnn. +.le +SEE ALSO +apbackground, apedit, apfind, icfit +.endhelp diff --git a/noao/twodspec/apextract/doc/apedit.hlp b/noao/twodspec/apextract/doc/apedit.hlp new file mode 100644 index 00000000..324f6e5d --- /dev/null +++ b/noao/twodspec/apextract/doc/apedit.hlp @@ -0,0 +1,374 @@ +.help apedit Sep96 noao.twodspec.apextract +.ih +NAME +apedit -- Edit apertures +.ih +USAGE +apedit input +.ih +PARAMETERS +.ls input +List of input images for which apertures are to be edited. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +If the reference image list is shorter than the input image list the +last reference image is used for the remaining input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = no +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing is +disabled. +.le +.ls find = no +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = no +Recenter the apertures? +.le +.ls resize = no +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le + +.ls line = INDEF +The dispersion line (line or column perpendicular to the dispersion axis) to +be graphed. A value of INDEF uses the middle of the image. +.le +.ls nsum = 10 +Number of dispersion lines to be summed or medianed. The lines are taken +around the specified dispersion line. A positive nsum selects a sum of +lines and a negative selects a median of lines. +.le +.ls width = 5. +Width of spectrum profiles. This parameter is used for the profile +centering algorithm in this and other tasks. +.le +.ls radius = 5. +The profile centering error radius for the centering algorithm. +.le +.ls threshold = 0. +Centering threshold for the centering algorithm. The range of pixel intensities +near the initial centering position must exceed this threshold. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters are taken from the +task \fBapdefault\fR. Parameters for the various functions of finding, +recentering, and resizing are taken from the parameters for the +appropriate task. + +When this operation is performed from the task \fBapall\fR all parameters +except the package parameters are included in that task. +.ih +CURSOR KEYS +When editing the apertures interactively the following cursor keys are +available. + +.nf +? Print help +a Toggle the ALL flag +b an Set background fitting parameters +c an Center aperture(s) +d an Delete aperture(s) +e an Extract spectra (see APSUM) +f Find apertures up to the requested number (see APFIND) +g an Recenter aperture(s) (see APRECENTER) +i n Set aperture ID +j n Set aperture beam number +l ac Set lower limit of current aperture at cursor position +m Define and center a new aperture on the profile near the cursor +n Define a new aperture centered at the cursor +o n Enter desired aperture number for cursor selected aperture and + remaining apertures are reordered using apidtable and maxsep + parameters (see APFIND for ordering algorithm) +q Quit +r Redraw the graph +s an Shift the center(s) of the current aperture to the cursor + position +t ac Trace aperture positions (see APTRACE) +u ac Set upper limit of current aperture at cursor position +w Window the graph using the window cursor keys +y an Set aperture limits to intercept the data at the cursor y + position +z an Resize aperture(s) (see APRESIZE) +. n Select the aperture nearest the cursor for current aperture ++ c Select the next aperture (in ID) to be the current aperture +- c Select the previous aperture (in ID) to be the current aperture +I Interrupt task immediately. Database information is not saved. +.fi + +The letter a following the key indicates if all apertures are affected when +the ALL flag is set. The letter c indicates that the key affects the +current aperture while the letter n indicates that the key affects the +aperture whose center is nearest the cursor. +.ih +COLON COMMANDS + +.nf +:show [file] Print a list of the apertures (default STDOUT) +:parameters [file] Print current parameter values (default STDOUT) +:read [name] Read from database (default current image) +:write [name] Write to database (default current image) +.fi + +The remaining colon commands are task parameters and print the current +value if no value is given or reset the current value to that specified. +Use :parameters to see current parameter values. + +.nf +:apertures :apidtable :avglimits :b_function +:b_grow :b_high_reject :b_low_reject :b_naverage +:b_niterate :b_order :b_sample :background +:bkg :center :clean :database +:extras :gain :image :line +:llimit :logfile :lower :lsigma +:maxsep :minsep :npeaks :nsubaps +:nsum :order :parameters :peak +:plotfile :r_grow :radius :read +:readnoise :saturation :shift :show +:skybox :t_function :t_grow :t_high_reject +:t_low_reject :t_naverage :t_niterate :t_nsum +:t_order :t_sample :t_step :t_width +:threshold :title :ulimit :upper +:usigma :weights :width :write +:ylevel :t_nlost +.fi +.ih +DESCRIPTION +For each image in the input image list, apertures are defined and edited +interactively. The aperture editor is invoked when the parameters +\fIinteractive\fR and \fIedit\fR are both yes. When this is the case +the task will query whether to edit each image. The responses are +"yes", "no", "YES", and "NO", where the upper case responses suppress +queries for all following images. + +When the aperture editor is entered a graph of the image lines or +columns specified by the parameters \fIline\fR and \fInsum\fR is +drawn. In the \fBapextract\fR package a dispersion line is either a +line or column in the image at one point along the dispersion axis. +The dispersion axis may be defined in the image header under the +keyword DISPAXIS or by the package parameter \fIdispaxis\fR. The +parameter \fBnsum\fR determines how many dispersion lines surrounding +the specified dispersion line are summed or medianed. This improves the +signal in the profiles of weaker spectra. Once the graph is drawn an +interactive cursor loop is entered. The set of cursor keys and colon +commands is given above and may be printed when the task is running using +the '?' key. The CURSOR MODE keys and graph formatting options are also +available (see \fBcursor\fR and \fBgtools\fR). + +A status line, usually at the bottom of the graphics terminal, +indicates the current aperture and shows the ALL flag, 'a' key, if set. The +concept of the current aperture is used by several of the aperture +editing commands. Other commands operate on the aperture whose center +is nearest the cursor. It is important to know which commands operate +on the current aperture and which operate on the nearest aperture to +the cursor. + +The cursor keys and colon commands are used to define new apertures, +delete existing apertures, modify the aperture number, beam number, +title, center, and limits, set background fitting parameters, trace the +positions of the spectra in the apertures, and extract aperture +spectra. When creating new apertures default parameters are supplied +in two ways; if no apertures are defined then the default parameters +are taken from the task \fBapdefault\fR while if there is a current +aperture then a copy of its parameters are made. + +The keys for creating a new aperture are 'm' and 'n' and 'f'. The key +'m' marks a new aperture and centers the aperture on the profile +nearest the cursor. The centering algorithm is described under the +help topic \fBcenter1d\fR and the parameters controlling the centering are +\fIwidth\fR, \fIradius\fR, and \fIthreshold\fR. The key 'n' defines a +new aperture at the position of the cursor without centering. This is +used if there is no spectrum profile such as when defining sky apertures +or when defining apertures in extended profiles. The 'f' key finds new +apertures using the algorithm described in the task \fBapfind\fR. The +number of apertures found in this way is limited by the parameter +\fBnfind\fR and the number includes any previously defined +apertures. The new aperture number, beam number, and title are assigned using +the aperture assignment algorithm described in \fBapfind\fR. + +The aperture number for the aperture \fInearest\fR the cursor is changed +with the 'j' key and the beam number is changed with the 'k' key. The +user is prompted for a new aperture number or beam number. The +aperture title may be set or changed with the :title colon command. + +The 'o' key may be used to reorder or correct the aperture +identifications and beam numbers. This is useful if the aperture +numbers become disordered due to deletions and additions or if the +first spectrum is missing when using the automatic identification +algorithm. An aperture number is requested for the aperture pointed to +by the cursor. The remaining apertures are reordered relative to this +aperture number. There is a aperture number, beam number, and title +assignment algorithm which uses information about the maximum +separation between consecutive apertures, the direction of increasing +aperture numbers, and an optional aperture identification table. See +\fBapfind\fR for a description of the algorithm. + +After defining a new aperture it becomes the current aperture. The +current aperture is indicated on the status line and the '.', '+', and +'-' keys are used to select a new current aperture. + +Apertures are deleted with 'd' key. The aperture \fInearest\fR the +cursor is deleted. + +The aperture center may be changed with the 'c', 's', and 'g' keys and the +":center value" colon command. The 'c' key applies the centering algorithm +to the aperture \fInearest\fR the colon. The 's' key shifts the center +of the \fIcurrent\fR aperture to the position of the cursor. The 'g' +applies the \fBaprecenter\fR algorithm. The :center command sets the +center of the \fIcurrent\fR aperture to the value specified. Except +for the last option these commands may be applied to all apertures +if the ALL flag is set. + +The aperture limits are defined relative to the aperture center. The +limits may be changed with the 'l', 'u', 'y', and 'z' keys and with the +":lower value" and ":upper value" commands. The 'l' and 'u' keys set +the lower and upper limits of the \fIcurrent\fR aperture at the position +of the cursor. The colon commands allow setting the limits explicitly. +The 'y' key defines both limits for the \fInearest\fR aperture as +points at which the y cursor position intercepts the data profile. +This requires that the aperture include a spectrum profile and that +the y cursor value lie below the peak of the profile. The 'z' +key applies the \fBapresize\fR algorithm. Except for the colon +commands these commands may be applied to all apertures if the ALL +flag is set. + +The key 'b' modifies the background fitting parameters for the aperture +\fInearest\fR the cursor. The default background parameters are +specified by the task \fBapdefault\fR. Note that even though +background parameters are defined, background subtraction is not +performed during extraction unless specified. +When the 'b' key is used the \fBicfit\fR graphical interface is entered +showing the background regions and function fit for the current image +line. Note that the background regions are specified relative to +the aperture center and follows changes in the aperture position. + +The two types of +extraction which may be specified are to average all points within +a set of background regions or fit a function to the points in +the background regions. In the first case only the background sample +parameter is used. In the latter case the other parameters are +also used in conjunction with the \fBicfit\fR function fitting commands. +See \fBapbackground\fR for more on the background parameters. + +Each aperture may have different background +fitting parameters but newly defined apertures inherit the background +fitting parameters of the last current aperture. This will usually be +satisfactory since the background regions are defined relative to the +aperture center rather than in absolute coordinates. If the ALL flag +is set then all apertures will be given the same background +parameters. + +The algorithms used in the tasks \fBapfind, aprecenter, apresize, aptrace\fR, +and \fBapsum\fR are available from the editor with the keys 'f', 'g', 'z', +'t', and 'e' +respectively. Excluding finding, if the ALL flag is not set then the +nearest aperture +to the cursor is used. This allows selective recentering, resizing, +tracing and extracting. +If the ALL flag is set then all apertures are traced or extracted. +When extracting the output, rootname and profile name are queried. + +Some general purpose keys window the graph 'w' using the \fBgtools\fR +commands, redraw the graph 'r', and quit 'q'. + +The final cursor key is the 'a' key. The cursor keys which modify the +apertures were defined as operating on either the aperture nearest the +cursor or the current aperture. The 'a' key allows these keys to +affect all the apertures simultaneously. The 'a' key sets a flag which +is shown on the status line when it is set. When set, the operation on +one aperture is duplicated on the remaining apertures. The operations +which apply to all apertures are set background 'b', center 'c', delete +'d', extract 'e', recenter 'g', set lower limit 'l', shift 's', trace +'t', set upper limit 'u', set limits at the y cursor 'y', and resize +'z'. The 'b', 'l', 's', and 'u' keys first set the background, +aperture limits, or shift for the appropriate aperture and then are +applied to the other apertures relative to their centers. + +All the parameters used in any of the operations may be examined or +changed through colon commands. The :parameters command lists all +parameter values and :show lists the apertures. The :read and :write +are used to force an update or save the current apertures and to read +apertures for the current image or from some other image. The commands +all have optional arguments. For the commands which show information +the argument specifies a file to which the information is to be +written. The default is the standard output. The database read and +write and the change image commands take an image name. If an image +name is not given for the read and write commands the +current image name is used. The change image command default is to +print the current image name. The remaining commands take a value. If +a value is not given then the current value is printed. + +The aperture editor may be selected from nearly every task using the +\fBedit\fR parameter. +.ih +EXAMPLES +The aperture editor is a very flexible and interactive tool +for which it is impossible illustrate all likely uses. The following +give some simple examples. + +1. To define and edit apertures for image "n1.001": + + cl> apedit n1.001 + +2. To define apertures for one image and then apply them to several other +images: + +.nf + cl> apedit n1.* ref=n1.001 + Edit apertures for n1.001? (yes) + Edit apertures for n1.002? (yes) NO +.fi + +Answer "yes" to the first query for editing n1.001. To +the next query (for n1.002) respond with "NO". The remaining +images then will not be edited interactively. Note that after +defining the apertures for n1.001 they are recorded in the database +and subsequent images will be able to use them as reference apertures. + +3. Using the ":image name" and ":read image" colon commands and the +'f', 'g', 'z', 't' and 'e' keys the user can perform all the functions +available in the package without ever leaving the editor. The 'a' key +to set the ALL flag is very useful when dealing with many spectra in a +single image. +.ih +.ih +REVISIONS +.ls APEDIT V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". + +The aperture ID table information may now be contained in the +image header under the keywords SLFIBnnn. +.le +SEE ALSO +.nf +apdefault, apfind, aprecenter, apresize, aptrace, apsum, apall +center1d, cursor, gtools, icfit +.fi +.endhelp diff --git a/noao/twodspec/apextract/doc/apextract.hlp b/noao/twodspec/apextract/doc/apextract.hlp new file mode 100644 index 00000000..401d93e7 --- /dev/null +++ b/noao/twodspec/apextract/doc/apextract.hlp @@ -0,0 +1,365 @@ +.help package Feb94 noao.twodspec.apextract +.ih +NAME +apextract -- Identify, manipulate, and extract spectra in 2D images +.ih +USAGE +apextract +.ih +PARAMETERS +.ls dispaxis = 2 +Image axis along which the spectra dispersion run. The dispersion axis +is 1 when the dispersion is along lines so that spectra are horizontal +when displayed normally. The dispersion axis is 2 when the dispersion +is along columns so that spectra are vertical when displayed normally. +This parameter is superseded when the dispersion axis is defined in +the image header by the parameter DISPAXIS. +.le +.ls database = "database" +Database for storing aperture definitions. Currently the database is +a subdirectory of text files with prefix "ap" followed by the entry name, +usually the image name. +.le +.ls verbose = no +Print detailed processing and log information? The output is to the +standard output stream which is the user's terminal unless redirected. +.le +.ls logfile = "" +Text logfile of operations performed. If a file name is specified +log and history information produced by all the tasks in the package +is appended to the file. +.le +.ls plotfile = "" +Binary plot metacode file of aperture locations, traces, rejected points, +etc. If a file name is given metacode plots are appended. The contents +of the file may be manipulated with the tasks in the \fBplot\fR package. +The most common is \fBgkimosaic\fR. Special plotfile names may be used +to select only particular plots or plots not normally output. These are +debugall, debugfitspec, debugaps, debugspec, debugfits, debugtrace, +and debugclean which plot everything, the fitted spectrum, the apertures, +the extracted spectrum, profile fit plots, the trace, and the rejected +points during cleaned extraction. +.le +.ls version = "APEXTRACT V3.0: August 1990" +Version of the package. This is the third major version of the package. +.le +.ih +DESCRIPTION +The primary function of the \fBapextract\fR package is the extraction of +spectra from two dimensional formats to one dimensional formats. In +other words, the pixels at each wavelength are summed, possibly +subtracting a background or sky from other pixels at that wavelength, +to produce a vector of spectral fluxes as a function of wavelength. +It has become common to have many spectra in one two dimensional +image produced by instruments using echelles, fibers, and aperture +masks. Thus, the package provides many features for the efficient +extractions of multiple spectra as well as single spectra. There are +also some additional, special purpose tasks for modeling spectra +and using the aperture definitions, described below, +to create masks and modified flat field images. + +The package assumes that one of the image axes is the dispersion axis, +specified by the \fIdispaxis\fR package parameter or image header +parameter of the same name, and the other is the spatial axes. +This means that all pixels at the same column or line (the +orientation may be in either direction) are considered to be at the +same wavelength. Even if this is not exactly +true the resolution loss is generally quite small and the simplicity and +absence of interpolation problems justify this approach. The +alternatives are to rotate the image with \fBrotate\fR or use the more +complex \fBlongslit\fR package. Though extraction is strictly along +lines and columns the position of the spectrum along the spatial axis +is allowed to shift smoothly with wavelength. This accounts for small +misalignments and distortions. + +The two dimensional regions occupied by the spectra are defined by +digital apertures having a fixed width but with spatial position smoothly +varying with wavelength. The apertures have a number of attributes. +The aperture definitions are created and modified by the tasks in this +package and stored in a database specified by the parameter \fIdatabase\fR. +The database is currently a directory containing simple text files +in a human readable format. The elements of an aperture definition +are as follows. + + +.ce +Elements of an Aperture Definition +.ls aperture +An integer aperture identification number. The aperture number +must be unique within a set of apertures. The aperture number is +the primary means of referencing an aperture and the resulting +extracted spectra. The aperture numbers are part of the extracted +spectra image headers. The numbers may be any integer and in any order +but the most typical case is to have sequential numbers beginning +with 1. +.le +.ls beam +An integer beam number. The beam number need not be unique; i.e. +several apertures may have the same beam number. The beam numbers are +recorded in the image headers of the extracted spectra. The beam +number is often used to identify types of spectra such as object, +sky, arc, etc. +.le +.ls center +A pair of numbers specifying the center of the aperture along the spatial +and dispersion axes in the two dimensional image. The center along +the dispersion is usually defined as the middle of the image. The +rest of the aperture parameters are defined relative to the aperture +center making it easy to move apertures. +.le +.ls low, high +Pairs of numbers specifying the lower and upper limits of the +aperture relative to the center along the spatial and dispersion axes. +The lower limits are usually negative and the upper limits positive +but there is no actual restriction; i.e. the aperture can actually +be offset from the center position. Currently the dispersion +aperture limits are such that the entire length of the image along the +dispersion axis is used. In the future this definition can be +easily used for objective prism spectra. +.le +.ls curve, axis +An IRAF "curfit" function specifying a shift to be added to the center +position along the spatial axis, given by the axis parameter which is +the complement of the dispersion axis parameter \fIdispaxis\fR, as a +function of the dispersion coordinate. This trace function is one of +the standard IRAF \fBicfit\fR types; a legendre polynomial, a chebyshev +polynomial, a linear spline, or a cubic spline. +.le +.ls background +Background definition parameters. For the "average" background subtraction +option only the set of background sample regions (defined relative to +the aperture center) are used. For the "fit" option the parameters +are those used by the \fBicfit\fR package for fitting a function to +the points in the background sample regions. +.le + +This information as well as the image (or database entry) name are stored +in a text file, with name given by the prefix "ap" followed by the entry +name, in the database directory. An example with the special entry name +"last", stored in the file "database$aplast", is given below. The "begin" +line marks the beginning of an aperture definition. + + +.ce +Sample Aperture Database Entry + +.nf +# Fri 17:43:41 03-Aug-90 +begin aperture last 1 70.74564 256. + image last + aperture 1 + beam 1 + center 70.74564 256. + low -5. -255. + high 5. 256. + background + xmin -100. + xmax 100. + function chebyshev + order 1 + sample -10:-6,6:10 + naverage -3 + niterate 0 + low_reject 3. + high_reject 3. + grow 0. + axis 1 + curve 5 + 2. + 1. + 1. + 512. + 0. +.fi + +There are a number of logical functions which may be performed to +create, modify, and use the aperture definitions. These functions +are: +.ls o +Automatically find a specified number of spectra and assign default +apertures. Apertures may also be inherited from another image or +defined using an interactive graphical interface called the \fIaperture +editor\fR. +.le +.ls o +Recenter apertures on the image spectrum profiles. +.le +.ls o +Resize apertures based on spectrum profile width. +.le +.ls o +Interactively define or adjust aperture definitions using a graphical +interface called the \fIaperture editor\fR. All function may also +be performed from this editor and, so, provides an alternative +method of processing and extracting spectra. +.le +.ls o +Trace the positions of spectra profiles from a starting image line +or column to other image lines or columns and fit a smooth function. +The trace function is used to shift the center of the apertures +at each dispersion point in the image. +.le +.ls o +Extract the flux in the apertures into one dimensional spectra in various +formats. This includes possible background subtraction, variance +weighting, and bad pixel rejection. +.le + +The package is logically organized around these functions. Each +function has a task devoted to it. The description of the parameters +and algorithms for each function are organized according to these +tasks; namely under the help topics \fBapdefault, apfind, aprecenter, +apresize, apedit, aptrace\fR, and \fBapsum\fR. However, each task has +parameters to allow selecting some or all of the other functions, hence +it is not necessary to use the individual tasks and often it is more +convenient to use just the extraction task for all operations. It is +also possible to perform all the functions from within a graphical +interface called the aperture editor. This is usually only used to +define and modify aperture definitions but it also has the capability +to trace spectra and extract them. + +Each of the functions has many different options and parameters. When +broken down into individual tasks the parameters are also sorted by +their function though there are then some mutual interdependencies. +This parameter decomposition was what was available prior to the +addition of the task \fBapall\fR. This is the central task of the +package which performs any and all of the functions required for the +extraction of spectra and also collects all the parameters into one +parameter set. It is recommended that \fBapall\fR be used because it +collects all the parameters in one place eliminating confusion over +where a particular parameter is defined. + +In summary, the package consists of a number of logical functions which +are documented by the individual tasks named for that function, but the +functions are also integrated into each task and the aperture editor to +providing many different ways for the user to choose to perform the +functions. + +The package menu and help summary is shown below. + + +.ce +The APEXTRACT Package Tasks + +.nf + apall apedit apflatten aprecenter apsum + apdefault apfind apmask apresize aptrace + apdemos apfit apnormalize apscatter + + apall - Extract 1D spectra (all parameters in one task) + apdefault - Set the default aperture parameters and apidtable + apdemos - Various tutorial demonstrations + apedit - Edit apertures interactively + apfind - Automatically find spectra and define apertures + apfit - Fit 2D spectra and output the fit, difference, + or ratio + apflatten - Remove overall spectral and profile shapes from + flat fields + apmask - Create and IRAF pixel list mask of the apertures + apnormalize - Normalize 2D apertures by 1D functions + aprecenter - Recenter apertures + apresize - Resize apertures + apscatter - Fit and subtract scattered light + apsum - Extract 1D spectra + aptrace - Trace positions of spectra + + Additional topics + + apbackground - Background subtraction algorithms + apextract - Package parameters and general description of + package + approfiles - Profile determination algorithms + apvariance - Extractions, variance weighting, cleaning, and + noise model +.fi + +The extracted spectra are recorded in one, two, or three dimensional +images depending on the \fIformat\fR and \fIextras\fR parameters. If +the \fIextras\fR parameter is set to yes the formats are three +dimensional with each plane in the third dimension containing +associated information for the spectra in the first plane. See +\fBapsum\fR for further details. When \fIextras\fR=no only the +extracted spectra are output. + +If the format parameter is "onedspec" the output extractions are one +dimensional images with names formed from an output rootname and an +aperture number extension; i.e. root.0001 for aperture 1. There will +be as many output images as there are apertures for each input image, +all with the same output rootname but with different aperture +extensions. This format is provided to be compatible with the original +format used by the \fBonedspec\fR package. + +If the format parameter is "echelle" or "multispec" the output aperture +extractions are put into a two dimensional image with a name formed from +the output rootname and the extension ".ec" or ".ms". Each line in +the output image corresponds to one aperture. Thus in this format +there is one output image for each input image. These are the preferred +output formats for reasons of compactness, ease of handling, and efficiency. +These formats are compatible with the \fBonedspec\fR, \fBechelle\fR, and +\fBmsred\fR packages. The format is a standard IRAF image with +specialized image header keywords. Below is an example of the keywords. + + +.ce +MULTISPEC/ECHELLE Format Image Header Keywords + +.nf + ap> imhead test.ms + test.ms[512,2,4][real]: Title + BANDID1 = 'spectrum - background fit, weights variance, clean yes' + BANDID2 = 'spectrum - background fit, weights none, clean no' + BANDID3 = 'background - background fit' + BANDID4 = 'sigma - background fit, weights variance, clean yes' + APNUM1 = '1 1 87.11 94.79' + APNUM2 = '2 1 107.11 114.79' + APID1 = 'Galaxy center' + APID2 = 'Galaxy edge' + WCSDIM = 3 + CTYPE1 = 'PIXEL ' + CTYPE2 = 'LINEAR ' + CTYPE3 = 'LINEAR ' + CRVAL1 = 1. + CRPIX1 = 1. + CD1_1 = 1. + CD2_2 = 1. + CD3_3 = 1. + LTM1_1 = 1. + LTM2_2 = 1. + LTM3_3 = 1. + WAT0_001= 'system=equispec + WAT1_001= 'wtype=linear label=Pixel + WAT2_001= 'wtype=linear + WAT3_001= 'wtype=linear +.fi + +The BANDIDn keywords describe the various elements of the 3rd dimension. +Except for the first one the other bands only occur when \fIextras\fR is +yes and when sky subtraction and/or variance and cleaning are done. The +relation between the line and the aperture numbers is given by the header +parameters APNUMn where n is the line and the value gives extraction and +coordinate information about the spectrum. The first field is the aperture +number and the second is the beam number. After dispersion calibration of +echelle format spectra the beam number becomes the order number. The other +two numbers are the aperture limits at the line or column at which the +aperture was defined. +The APID keywords provide an optional title for each extracted spectrum +in addition to the overall image title. + +The rest of the keywords are part of the IRAF World Coordinate System +(WCS). If the image being extracted has been previously calibrated +(say with \fBlongslit.transform\fR) then the dispersion coordinates +will be carried in CRVAL1 and CD1_1. + +There is one other value for the format parameter, "strip". This produces +two dimensional extractions rather than one dimensional extractions. +Each aperture is output to a two dimensional image with a width set by the +nearest integer which includes the aperture. The output names are +generated in the same way as for "onedspec" format. The aperture is +shifted by interpolation so that it is exactly aligned with the image +columns. If not variance weighting the actual image data is output +with appropriate shifting while for variance weighting and/or cleaning +the profile model is output (similar to \fBapfit\fR except for being +aligned). This format is that provided in the previous version of +the package by the \fBapstrip\fR task. It is now relegated to a +special case. +.endhelp diff --git a/noao/twodspec/apextract/doc/apextractsys.hlp b/noao/twodspec/apextract/doc/apextractsys.hlp new file mode 100644 index 00000000..a93d9f56 --- /dev/null +++ b/noao/twodspec/apextract/doc/apextractsys.hlp @@ -0,0 +1,415 @@ +.help apextract Aug90 noao.twodspec.apextract + +.ce +APEXTRACT System Notes + + +\fBIntroduction\fR + +The \fBapextract\fR package is a complex package with a simple +purpose, the extraction of one dimensional spectra from two dimensional +images. The complexity arises from the many algorithms and parameters +involved. To manage the complexity of the algorithms, features, parameters, +functionality, and documentation the package has been organized in terms +of logical functions which may be invoked in a number of ways. The +logical functions are: +.ls o +Automatically find a specified number of spectra and assign default +apertures. Apertures may also be inherited from another image or +defined using an interactive graphical interface called the \fIaperture +editor\fR. +.le +.ls o +Recenter apertures on the image spectrum profiles. +.le +.ls o +Resize apertures based on spectrum profile width. +.le +.ls o +Interactively define or adjust aperture definitions using a graphical +interface called the \fIaperture editor\fR. All function may also +be performed from this editor and, so, provides an alternative +method of processing and extracting spectra. +.le +.ls o +Trace the positions of spectra profiles from a starting image line +or column to other image lines or columns and fit a smooth function. +The trace function is used to shift the center of the apertures +at each dispersion point in the image. +.le +.ls o +Extract the flux in the apertures into one dimensional spectra in various +formats. This includes possible background subtraction, variance +weighting, and bad pixel rejection. +.le + +The package is logically organized around these functions. Each +function has a task devoted to it. The description of the parameters +and algorithms for each function are organized according to these +tasks; namely under the help topics \fBapdefault, apfind, aprecenter, +apresize, apedit, aptrace\fR, and \fBapsum\fR. However, each task has +parameters to allow selecting some or all of the other functions, hence +it is not necessary to use the individual tasks and often it is more +convenient to use just the extraction task for all operations. It is +also possible to perform all the functions from within a graphical +interface called the aperture editor. This is usually only used to +define and modify aperture definitions but it also has the capability +to trace spectra and extract them. + +Each of the functions has many different options and parameters. When +broken down into individual tasks the parameters are also sorted by +their function though there are then some mutual interdependencies. +This parameter decomposition was what was available prior to the +addition of the task \fBapall\fR. This is the central task of the +package which performs any and all of the functions required for the +extraction of spectra and also collects all the parameters into one +parameter set. It is recommended that \fBapall\fR be used because it +collects all the parameters in one place eliminating confusion over +where a particular parameter is defined. + +In summary, the package consists of a number of logical functions which +are documented by the individual tasks named for that function, but the +functions are also integrated into each task and the aperture editor to +providing many different ways for the user to choose to perform the +functions. + +This document describes some of the implementation details and features +which are hidden from the normal user. + + +\fBParameters\fR + +The tasks actually use hidden parameter sets for almost all parameters. +To see all the parameter sets type + +.nf + ap> ?_ apextract +.fi + +The relation between the tasks and the hidden parameter sets is given below. + +.nf + PSET TASK + apparams - apdefault, apfind, aprecenter, apresize, + apedit, aptrace, apsum, apmask, apscatter + apall1 - apall + apfit1 - apfit + apflat1 - apflatten + apnorm1 - apnormalize +.fi + +The hidden parameter sets may be viewed in any of the normal ways +\fBeparam\fR, \fBlparam\fR, or just by typing their name, except +their names may not be abbreviated. Their purpose is to redirect +parameters to visible parameter sets, to hide some parameters which +are not meant to be changed by the user, and to include parameters +used for queries. + +Most of the redirected parameters go to a single visible parameter set +or to package parameters. +The interesting exception is \fBapparams\fR which provides the +parameter linkage between the various functional tasks like +\fBapfind\fR, \fBaptrace\fR, \fBapsum\fR, etc. Below is a reproduction +of this parameter set. + +.ce +APPARAMS Hidden Parameter Set + +.nf + I R A F + Image Reduction and Analysis Facility +PACKAGE = apextract + TASK = apparams + +(format = )_.format) Extracted spectra format +(extras = )apsum.extras) Extract sky, sigma, etc.? +(dbwrite= yes) Write to database? +(initial= yes) Initialize answers? +(verbose= )_.verbose) Verbose output? + + # DEFAULT APERTURE PARAMETERS + +(upper = )apdefault.upper) Upper aperture limit relative to center +(apidtab= )apdefault.apidtable) Aperture ID table (optional) + + # DEFAULT BACKGROUND PARAMETERS + +(b_funct= )apdefault.b_function) Background function +(b_order= )apdefault.b_order) Background function order +(b_sampl= )apdefault.b_sample) Background sample regions +(b_naver= )apdefault.b_naverage) Background average or median +(b_niter= )apdefault.b_niterate) Background rejection iterations +(b_low_r= )apdefault.b_low_reject) Background lower rejection sigma +(b_high_= )apdefault.b_high_reject) Background upper rejection sigma +(b_grow = )apdefault.b_grow) Background rejection growing radius + + # APERTURE CENTERING PARAMETERS + +(width = )apedit.width) Profile centering width +(radius = )apedit.radius) Profile centering radius +(thresho= )apedit.threshold) Detection threshold for profile centering + + # AUTOMATIC FINDING AND ORDERING PARAMETERS + +(nfind = )apfind.nfind) Number of apertures to be found automatically +(minsep = )apfind.minsep) Minimum separation between spectra +(maxsep = )apfind.maxsep) Maximum separation between spectra +(order = )apfind.order) Order of apertures + + # RECENTERING PARAMETERS + +(apertur= )aprecenter.apertures) Select apertures +(npeaks = )aprecenter.npeaks) Select brightest peaks +(shift = )aprecenter.shift) Use average shift instead of recentering? + + # RESIZING PARAMETERS + +(llimit = )apresize.llimit) Lower aperture limit relative to center +(ulimit = )apresize.ulimit) Upper aperture limit relative to center +(ylevel = )apresize.ylevel) Fraction of peak or intensity for automatic widt(peak = )apresize.peak) Is ylevel a fraction of the peak? +(bkg = )apresize.bkg) Subtract background in automatic width? +(r_grow = )apresize.r_grow) Grow limits by this factor +(avglimi= )apresize.avglimits) Average limits over all apertures? + + # EDITING PARAMETERS + +e_output= Output spectra rootname +e_profil= Profile reference image +(t_nsum = )aptrace.nsum) Number of dispersion lines to sum +(t_step = )aptrace.step) Tracing step +(t_width= )apedit.width) Centering width for tracing +(t_funct= )aptrace.function) Trace fitting function +(t_order= )aptrace.order) Trace fitting function order +(t_sampl= )aptrace.sample) Trace sample regions +(t_naver= )aptrace.naverage) Trace average or median +(t_niter= )aptrace.niterate) Trace rejection iterations +(t_low_r= )aptrace.low_reject) Trace lower rejection sigma +(t_high_= )aptrace.high_reject) Trace upper rejection sigma +(t_grow = )aptrace.grow) Trace rejection growing radius + + # EXTRACTION PARAMETERS + +(backgro= )apsum.background) Background to subtract (none|average|fit) +(skybox = )apsum.skybox) Box car smoothing length for sky +(weights= )apsum.weights) Extraction weights (none|variance) +(clean = )apsum.clean) Detect and replace bad pixels? +(niterat= 2) Number of profile fitting iterations +(saturat= )apsum.saturation) Saturation level +(readnoi= )apsum.readnoise) Read out noise sigma (photons) +(gain = )apsum.gain) Photon gain (photons/data number) +(lsigma = )apsum.lsigma) Lower rejection threshold +(usigma = )apsum.usigma) Upper rejection threshold +(maxtilt= 3) Maximum excursion for line/column fitting +(polysep= 0.95) Marsh algorithm polynomial spacing +(polyord= 10) Marsh algorithm polynomial order +(nsubaps= )apsum.nsubaps) Number of subapertures per aperture + + # ANSWER PARAMETERS + +(ansclob= no) +(ansclob= no) +(ansdbwr= yes) +(ansdbwr= yes) +(ansedit= yes) +(ansextr= yes) +(ansfind= yes) +(ansfit = yes) +(ansfits= yes) +(ansfits= yes) +(ansfits= yes) +(ansfits= yes) +(ansfitt= yes) +(ansfitt= yes) +(ansflat= yes) +(ansmask= yes) +(ansnorm= yes) +(ansrece= yes) +(ansresi= yes) +(ansrevi= yes) +(ansrevi= yes) +(ansscat= yes) +(anssmoo= yes) +(anstrac= no) +(mode = q) +.fi + +Note how the parameters are redirected to a variety of tasks. + + +\fBInvisible Parameters\fR + +The following algorithm parameters are not visible to the normal user +and are described only here. +.ls dbwrite = yes +Write to database? Writing to the database is a function just like +find, edit, extract, etc. When the task is interactive a query is +made whether to write to the database which may be answered with the +usual four values. When noninteractive the database writing is automatic. +This parameter provides the possibility of turning off database writing. +.le +.ls initialize = yes +Initialize default queries? Normally each invocation of a task results +in new queries independent of the last responses in a prior invocation +and based only on the functions selected; NO for those not selected and +yes for those selected. By setting this to no either the prior values +may be used or the response values may be set independently of the +function flags. This is used in scripts to tie together different +invocations of the task and to finely control the queries. +.le +.ls e_output, e_profile +These are query parameters used when extraction is invoked from the +aperture editor. +.le + +The following parameters are part of the variance weighted and cleaning +extractions. They are described further in \fBapprofiles\fR. +.ls niterate = 2 +Number of rejection iterations in the profile determination when cleaning. +Iteration of the profile is slow and the low order fitting function +is not very sensitive to deviant points. +.le +.ls maxtilt = 3 +Maximum excursion separating the two profile fitting algorithms. +.le +.ls polysep = 0.95 +Marsh algorithm polynomial spacing. +.le +.ls polyorder = 10 +Marsh algorithm polynomial order. +.le + + +\fBQuery Mechanism and Invisible Query Parameters\fR + +The querying mechanism of the \fBapextract\fR package is a nice feature +but has some complexities in implementation. At the bottom of the +mechanism are CL checks of the parameters described below. The parameter +is accessed first as a hidden parameter. If the value is YES or NO +then the appropriate function is performed or not. If the value is +lower case then the task supplies a prompt string, which varies by +including the image and/or aperture involved, the mode of the +parameter is changed to query, and the parameter is requested again +leading to a CL query of the user with the current default value. +Finally, the parameter is returned to hidden mode. + +If the \fIinitialize\fR parameter is no then the initial default +query values are those set before the task is invoked. This provides +very fine control of the query mechanism and linking different +invocations of the tasks to previous user responses. It is intended +only for complex scripts such as those in the spectroscopic \fBimred\fR +packages. Normally the initial values of the parameters are set +during task startup based on the function flags. If a flag is no +then the related query parameter is NO. If the function flag is yes +then when the task is interactive the initial value is yes otherwise +it is YES. The solely interactive functions, such as editing, are +set to NO when the task is noninteractive regardless of the function +selection. +.ls ansclobber, ansclobber1 +Used to define the action to be taken if an output image would be clobbered. +Normally the action is to query if interactive and not clobber if +noninteractive. The first parameter acts as the function switch and +the second as the actual query. +.le +.ls ansdbwrite, ansdbwrite1 +The second parameter is used by the task to mark whether any changes have +been made that might require a database update. The first parameter is +the actual query parameter for the \fIdbwrite\fR function flag. +.le +.ls ansedit +Query parameter for the interactive editing function. +.le +.ls ansextract +Query parameter for the extraction function. +.le +.ls ansfind +Query parameter for the find function. +.le +.ls ansfit +Query parameter for the fit function of \fBapfit\fR. +.le +.ls ansfitscatter +Query parameter for the interactive fitscatter function of \fBapscatter\fR. +.le +.ls ansfitsmooth +Query parameter for the interactive fitsmooth function of \fBapscatter\fR. +.le +.ls ansfitspec +Query parameter for the interactive fitspec function of \fBapflatten\fR +and \fBapnormalize\fR. This applies to each image. +.le +.ls ansfitspec1 +Query parameter for the interactive fitspec function of \fBapflatten\fR +and \fBapnormalize\fR. This applies to each aperture in an image. +.le +.ls ansfittrace +Query parameter for the interactive fittrace function. +This applies to each image. +.le +.ls ansfittrace1 +Query parameter for the interactive fittrace function. +This applies to each aperture in an image. +.le +.ls ansflat +Query parameter for the flatten function of \fBapflatten\fR. +.le +.ls ansmask +Query parameter for the mask function of \fBapmask\fR. +.le +.ls ansnorm +Query parameter for the normalize function of \fBapnormalize\fR. +.le +.ls ansrecenter +Query parameter for the recenter function. +.le +.ls ansresize +Query parameter for the resize function. +.le +.ls ansreview +Query parameter for the interactive extraction review function. +This applies to each image. +.le +.ls ansreview1 +Query parameter for the interactive extraction review function. +This applies to each aperture in an image. +.le +.ls ansscat +Query parameter for the subtract function of \fBapscatter\fR. +.le +.ls anssmooth +Query parameter for the smooth function of \fBapscatter\fR. +.le +.ls anstrace +Query parameter for the trace function. +.le + + +\fBTask Entry Points\fR + +Logical tasks in IRAF are organized as multiple procedures in one physical +task selected by the IRAF main. The \fBapextract\fR package extends +this concept to a lower level. All of the package tasks go through +one procedure, \fBapall\fR. This procedure handles all of the +startup details and breaks the logical task down into selected +functions which are implemented as other procedures. There are +a couple of interesting and unusual features of this organization. + +IRAF physical tasks may map multiple logical task names to the same +procedure. However, the procedure will not know under what name it +was called. In this package we want to know the logical task name +in order to select the appropriate hidden parameter set and to +make minor adjustments in what the tasks do while maintaining the +same basic logical flow and source code. To do this dummy entry +points are used whose only function is to call \fBapall\fR and +pass an indication of the task name. + +Based on the task name a named parameter set is opened with \fBclopset\fR +and then all CLIO calls use the returned pointer and can be blind to the +actual parameter set used. + +In addition to the tasks defined in the package and their associated +parameter sets there is one more task entry point called \fBapscript\fR +with parameter set \fBapscript\fR. It is intended for use in scripts +as it's name implies. For this reason it does not need an intermediate +hidden parameter set. For examples of it's use see the \fBimred\fR +packages such as \fBnessie\fR. +.endhelp diff --git a/noao/twodspec/apextract/doc/apextras.hlp b/noao/twodspec/apextract/doc/apextras.hlp new file mode 100644 index 00000000..36a51b26 --- /dev/null +++ b/noao/twodspec/apextract/doc/apextras.hlp @@ -0,0 +1,61 @@ +.help extras Sep95 noao.twodspec.apextract +.ih +NAME +extras -- Information about the extra bands in 3D output +.ih +DESCRIPTION +When one dimensional spectra are extracted by the tasks in the +\fBapextract\fR package the user may specify that additional +extra associated information be extracted at the same time. This +information is produced when the \fIextras\fR parameter is "yes". + +The associated information is recorded as additional "bands" (the IRAF term +for the third dimension of a three dimensional image) of the output +extracted spectral image. Extracted spectra are currently stored as IRAF +images with dispersion information given in the image header. The +image axes for such images are: + +.nf + 1 (columns) - dispersion axis + 2 (lines) - spectrum axis (each line is a separate spectrum) + 3 (bands) - extras axis (each band is associated data) +.fi + +The lengths of the second and third axes, that is the number of +lines and bands, may be one or more. If there is only one band +the image will be two dimensional and if there is only one line +and one band the image will be one dimensional. Note that the +\fIformat\fR parameter controls whether multiple apertures are +written to separate images or to a single image. Thus, if +the format is "onedspec" this means that the second dimension +will always be of length one and, if the \fIextras\fR parameter +is no, the output images will be one dimensional. + +The associated data in the image bands depends on which extraction +options are performed. The various types of data are: + +.nf + The primary spectrum flux values. + Simple aperture sum if variance weighting or cleaning was done. + Background spectrum if background subtraction was done. + Sigma spectrum if variance weighting or cleaning was done. +.fi + +The primary spectrum is always the first band and will be the cleaned +and/or variance weighted and/or background subtracted spectrum. The +simple aperture sum spectrum allows comparing against the results of the +variance weighting or pixel rejection options. When background +subtraction is performed the subtracted background is recorded in +one of the bands. When variance weighting or pixel rejection is +performed the software generates an estimate of the uncertainty +in the extracted flux as a sigma. + +The identity of the various bands is given by the image header +keywords BANDIDn (where n is the band number). This also serves +to document which extraction options were used. + +For more information get help under the topic "apextract.package". +.ih +SEE ALSO +apextract.package +.endhelp diff --git a/noao/twodspec/apextract/doc/apfind.hlp b/noao/twodspec/apextract/doc/apfind.hlp new file mode 100644 index 00000000..65260394 --- /dev/null +++ b/noao/twodspec/apextract/doc/apfind.hlp @@ -0,0 +1,180 @@ +.help apfind Sep96 noao.twodspec.apextract +.ih +NAME +apfind -- Find spectra and define apertures automatically +.ih +USAGE +apfind input +.ih +PARAMETERS +.ls input +List of input images in which spectra are to be identified and +apertures defined automatically. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = no +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing is +disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database and the +parameter \fInfind\fR must be greater than zero. +.le +.ls recenter = no +Recenter the apertures? +.le +.ls resize = no +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le + +.ls line = INDEF +The dispersion line (line or column perpendicular to the dispersion axis) to +be used in finding the spectra. A value of INDEF selects the middle of the +image. +.le +.ls nsum = 1 +Number of dispersion lines to be summed or medianed. The lines are taken +around the specified dispersion line. A positive value sums lines and +a negative value medians lines. +.le +.ls nfind = 1 +Maximum number of apertures to be defined. This is a query parameter +so the user is queried for a value except when given explicitly on +the command line. +.le +.ls minsep = 5. +Minimum separation between spectra. Weaker spectra or noise within this +distance of a stronger spectrum are rejected. +.le +.ls maxsep = 1000. +Maximum separation between adjacent spectra. This parameter +is used to identify missing spectra in uniformly spaced spectra produced +by fiber spectrographs. If two adjacent spectra exceed this separation +then it is assumed that a spectrum is missing and the aperture identification +assignments will be adjusted accordingly. +.le +.ls order = "increasing" +When assigning aperture identifications order the spectra "increasing" +or "decreasing" with increasing pixel position (left-to-right or +right-to-left in a cross-section plot of the image). +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters are taken from the +task \fBapdefault\fR, and parameters used for centering and editing the +apertures are taken from \fBapedit\fR. + +When this operation is performed from the task \fBapall\fR all parameters +except the package parameters are included in that task. +.ih +DESCRIPTION +For each image in the input image list spectra are identified and +default apertures defined. The automatic aperture finding is performed +only if 1) there are no apertures defined for the reference image, 2) +there are no apertures defined for the input image, 3) the parameter +\fIfind\fR is yes, and 4) the parameter \fInfind\fR is greater than +zero. + +The automatic finding algorithm uses the following steps. First, all local +maxima are found. The maxima are sorted by peak value and the weaker +of the peaks separated by less than the value given by the parameter +\fIminsep\fR are rejected. Finally, at most the \fInfind\fR strongests +peaks are kept. \fBNfind\fR is a query parameter, so if it is not +specified explicitly on the command line, the desired number of spectra +to be found is requested. After the peaks have been found the +\fBcenter1d\fR algorithm is used to refine the centers of the +profiles. Apertures having the default parameters set with the task +\fBapdefault\fR are defined at each center. This algorithm is also +available with the 'f' key in the task \fBapedit\fR with the change that +existing apertures are kept and count toward the maximum number +specified by \fBnfind\fR. + +The automatic assignment of aperture numbers, beam numbers, and titles +has several options. The simplest is when no aperture identification +table, parameter \fIapidtable\fR, is specified and the maximum separation +parameter, \fImaxsep\fR, is very large. In this case the aperture and +beam numbers are sequential starting from one and numbered either from +left-to-right or right-to-left depending on the \fIorder\fR parameter. +There are no aperture titles in this case. If two adjacent spectra are +separated by more than the specified maximum then the aperture numbers +jump by the integer part of the ratio of the separation to the +specified maximum separation. This is used when the image is expected +to have evenly spaced spectra, such as in multifiber spectrographs, in +which some may be missing due to broken fibers. Finally, the +aperture identification table (either a text file or an image +having a set of SLFIBnnn keyowrds) may contain lines with aperture number, +beam number, and (optional) title. The sequential numbers are then +indices into this table. Note that the skipping of missing spectra and +the ordering applies to entries in this table as well. + +The ways in which the automatic method can fail for evenly spaced +spectra with missing members are when the first spectrum is missing on +the side from which the ordering begins and when the expected rather +the actual number of spectra is used. In the first case one can use +the interactive 'o' key of the aperture editing facility to specify the +identity of any aperture and then all other apertures will be +appropriately reidentified. If more spectra are sought than actually +exist then noise spikes may be mistakenly found. This problem can be +eliminated by specifying the actual number of spectra or minimized by +using the threshold centering parameter. + +The \fIrecenter\fR parameter allows recentering apertures if defined by +a reference image. Since the purpose of this task is to find new +apertures it is usually the case that there are no reference images and +recentering is not done. The default apertures are of fixed width. +The \fIresize\fR parameter may be used to adjust the widths in a +variety of ways. The aperture positions and any other parameters may +also be edited with the aperture editing function if selected by the +\fIapedit\fR parameter and the task is run interactively. + +If the task is interactive the user is queried whether to perform +various steps on each image. The queries may be answered with one of +the four values "yes", "no", "YES" and "NO", where an upper case +response suppresses all further queries to this question. + +The aperture finding algorithm may be selected from nearly every task +in the package. +.ih +EXAMPLES + cl> apfind image nfind=10 +.ih +.ih +REVISIONS +.ls APFIND V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". + +The aperture ID table information may now be contained in the +image header under the keywords SLFIBnnn. +.le +SEE ALSO +center1d, apdefault, aprecenter, apresize, apedit, apall +.endhelp diff --git a/noao/twodspec/apextract/doc/apfit.hlp b/noao/twodspec/apextract/doc/apfit.hlp new file mode 100644 index 00000000..60dd9b4c --- /dev/null +++ b/noao/twodspec/apextract/doc/apfit.hlp @@ -0,0 +1,263 @@ +.help apfit Sep96 noao.twodspec.apextract +.ih +NAME +apfit -- Fit 2D spectra using APEXTRACT profile algorithms +.ih +USAGE +apfit input output fittype +.ih +PARAMETERS +.ls input +List of input images to be fit. +.le +.ls output = "" +List of output images to be created with the fitting results. If the null +string is given or the end of the output list is reached before the end +of the input list then the input image name is used and an extension +of ".fit", ".diff", or ".ratio" is added based on the type of fit. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and fit. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls fittype = "difference" +Type of fitted output. The choices are: +.ls "fit" +The fitted spectra are output. +.le +.ls "difference" +The difference (or residuals) of the data and the fit (data - fit). +.le +.ls "ratio" +The ratio of the data to the fit. If a fitted pixel goes below a specified +threshold the ratio is set to 1. +.le +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = yes +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing and trace +fitting are disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = yes +Recenter the apertures? +.le +.ls resize = yes +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace the apertures? +.le +.ls fittrace = yes +Interactively fit the traced positions by a function? The \fIinteractive\fR +parameter must also be yes. +.le +.ls fit = yes +Fit the spectra and produce a fitted output image? +.le + +The following two parameters are used in the finding, recentering, resizing, +editing, and tracing operations. +.ls line = INDEF +The starting dispersion line (line or column perpendicular to the dispersion +axis) for the tracing. A value of INDEF starts at the middle of the image. +.le +.ls nsum = 1 +Number of dispersion lines to be summed or medianed at each step along +the dispersion. For tracing only summing is done and the sign is +ignored. +.le + +.ls threshold = 10. +Division threshold for ratio fit type. If a pixel in the fitted spectrum +is less than this value then a ratio of 1 is output. +.le + +The following parameters control the profile and spectrum fitting. +.ls background = "none" +Type of background subtraction. The choices are "none" for no +background subtraction, "average" to average the background within the +background regions, or "fit" to fit across the dispersion using the +background within the background regions. Note that the "average" +option does not do any medianing or bad pixel checking; it is faster +than fitting however. Background subtraction also requires that the +background fitting parameters are properly defined. For the "average" +option only the background sample regions parameter is used. +.le +.ls pfit = "fit1d" (fit1d|fit2d) +Profile fitting algorithm to use with variance weighting or cleaning. +When determining a profile the two dimensional spectrum is divided by +an estimate of the one dimensional spectrum to form a normalized two +dimensional spectrum profile. This profile is then smoothed by fitting +one dimensional functions, "fit1d", along the lines or columns most closely +corresponding to the dispersion axis or a special two dimensional +function, "fit2d", described by Marsh (see \fBapprofile\fR). +.le +.ls clean = no +Detect and replace deviant pixels? +.le +.ls skybox = 1 +Box car smoothing length for sky background when using background +subtraction. Since the background noise is often the limiting factor +for good extraction one may box car smooth the sky to improve the +statistics in smooth background regions at the expense of distorting +the subtraction near spectral features. This is most appropriate when +the sky regions are limited due to a small slit length. +.le +.ls saturation = INDEF +Saturation or nonlinearity level. During variance weighted extractions +wavelength points having any pixels above this value are excluded from the +profile determination. +.le +.ls readnoise = 0. +Read out noise in photons. This parameter defines the minimum noise +sigma. It is defined in terms of photons (or electrons) and scales +to the data values through the gain parameter. A image header keyword +(case insensitive) may be specified to get the value from the image. +.le +.ls gain = 1 +Detector gain or conversion factor between photons/electrons and +data values. It is specified as the number of photons per data value. +A image header keyword (case insensitive) may be specified to get the value +from the image. +.le +.ls lsigma = 3., usigma = 3. +Lower and upper rejection thresholds, given as a number of times the +estimated sigma of a pixel, for cleaning. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters from +\fBapdefault\fR, automatic aperture finding parameters from +\fBapfind\fR, recentering parameters from \fBaprecenter\fR, resizing +parameters from \fBapresize\fR, parameters used for centering and +editing the apertures from \fBapedit\fR, and tracing parameters from +\fBaptrace\fR. +.ih +DESCRIPTION +The two dimensional spectra within the defined apertures of the input +images are fit by a model and new output images are created with either +the model spectra, the difference between the input and model spectra, +or the ratio of input and model spectra. The type of output is +selected by the parameter \fIfittype\fR which may have one of the +values "fit", "difference", or "ratio". + +Aperture definitions may be inherited from those of other images by +specifying a reference image with the \fBreferences\fR parameter. +Images in the reference list are matched with those in the +input list in order. If the reference image list is shorter than the +number of input images, the last reference image is used for all +remaining input images. Thus, a single reference image may be given +for all the input images or different reference images may be given for +each input image. The special reference name "last" may be used to +select the last set apertures used in any of the \fBapextract\fR tasks. + +If an aperture reference image is not specified or no apertures are +found for the specified reference image, previously defined apertures +for the input image are sought in the aperture database. Note that +reference apertures supersede apertures for the input image. If no +apertures are defined they may be created automatically, the \fIfind\fR +option, or interactively in the aperture editor, if the +\fIinteractive\fR and \fIedit\fR options are set. + +The functions performed by the task are selected by a set of flag +parameters. The functions are an automatic spectrum finding and +aperture defining algorithm (see \fBapfind\fR) which is ignored if +apertures are already defined, automatic recentering and resizing +algorithms (see \fBaprecenter\fR and \fBapresize\fR), an interactive +aperture editing function (see \fBapedit\fR), a spectrum position tracing +and trace function fit (see \fBaptrace\fR), and the main function of +this task, two dimensional model fitting. + +Each function selection will produce a query for each input spectrum if +the \fIinteractive\fR parameter is set. The queries are answered by +"yes", "no", "YES", or "NO", where the upper case responses suppress +the query for following images. There are other queries associated +with tracing which first ask whether the operation is to be done +interactively and, if yes, lead to queries for each aperture. If the +\fIinteractive\fR parameter is not set then aperture editing and +interactive trace fitting are ignored. + +The two dimensional spectrum model consists of a smooth two dimensional +normalized profile multiplied by the variance weighted one dimensional +spectrum. The profile is computed by dividing the data within the aperture +by the one dimensional spectrum, smoothing with either low order function +fits parallel to the dispersion axis or a special two dimensional function +as selected by the \fIpfit\fR parameter. The smooth profile is then used +to improve the spectrum estimate using variance weighting and to eliminate +deviant or cosmic ray pixels by sigma tests. The profile algorithm is +described in detail in \fBapprofiles\fR and the variance weighted spectrum +is described in \fBapvariance\fR. + +The process of determining the profile and variance weighted spectrum, +and hence the two dimensional spectrum model, is identical to that used +for variance weighted extraction of the one dimensional spectra in the +tasks \fBapall\fR or \fBapsum\fR. Most of the parameters of in this +task are the same as those in the extraction tasks and so further +information about them may be found in the descriptions of those tasks. + +Because of the connection with variance weighted extraction and cleaning +of one dimensional spectra, this task is useful as a diagnostic tool for +understanding and evaluating the variance weighting algorithm. +For example the "difference" image provides the residuals in a +two dimensional visual form. + +The "fit" output image does not include any background determination; +i.e the fit is background subtracted. Pixels outside the modeled +spectra are set to zero. + +The "difference" output image is simply the difference between the +background subtracted "fit" and the data. Thus the difference within +the apertures should approximate the background and outside the +apertures the difference will be identical with the input image. + +The "ratio" output image does include any background in the model +before taking the ratio of the data and model. If a model pixel +is less than the given \fIthreshold\fR parameter the output ratio +is set to one. This is used to avoid division by zero and set a +limit to noise in ratio image. Outside of the apertures the ratio +output pixels are set to one. +.ih +EXAMPLES +1. To compute the residuals of a model fit where the image already has +aperture defined: + + cl> apfit ls1 inter- rec- res- trace- read=3 gain=1 back=fit + +.ih +REVISIONS +.ls APFIND V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +SEE ALSO +apbackground, approfile, apvariance, +apdefault, apfind, aprecenter, apresize, apedit, aptrace, apsum, apall +.endhelp diff --git a/noao/twodspec/apextract/doc/apflatten.hlp b/noao/twodspec/apextract/doc/apflatten.hlp new file mode 100644 index 00000000..f7e1b8c0 --- /dev/null +++ b/noao/twodspec/apextract/doc/apflatten.hlp @@ -0,0 +1,304 @@ +.help apflatten Sep96 noao.twodspec.apextract +.ih +NAME +apflatten -- Create flat fields for fiber or narrow aperture spectra +.ih +USAGE +apflatten input output +.ih +PARAMETERS +.ls input +List of input flat field observations. +.le +.ls output = "" +List of output flat field images. If no output name is given then the +input name is used as a root with the extension ".flat". +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and flatten. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = yes +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing and trace +fitting are disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = yes +Recenter the apertures? +.le +.ls resize = yes +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace the apertures? +.le +.ls fittrace = yes +Interactively fit the traced positions by a function? The \fIinteractive\fR +parameter must also be yes. +.le +.ls flatten = yes +Remove the profile shape and flat field spectrum leaving only +sensitivity variations? +.le +.ls fitspec = yes +Fit normalization spectrum interactively? The \fIinteractive\fR +parameter must also be yes. +.le + +.ls line = INDEF, nsum = 1 +The dispersion line (line or column perpendicular to the dispersion +axis) and number of adjacent lines (half before and half after unless +at the end of the image) used in finding, recentering, resizing, +and editing operations. For tracing this is the starting line and +the same number of lines are summed at each tracing point. A line of +INDEF selects the middle of the image along the dispersion axis. +A positive nsum sums the lines and a negative value takes the median. +However, for tracing only sums are allowed and the absolute value +is used. +.le +.ls threshold = 10. +Division threshold. If a pixel in the two dimensional normalization spectrum +is less than this value then a flat field value of 1 is output. +.le + +The following parameters control the profile and spectrum fitting. +.ls pfit = "fit1d" (fit1d|fit2d) +Profile fitting algorithm to use with variance weighting or cleaning. +When determining a profile the two dimensional spectrum is divided by +an estimate of the one dimensional spectrum to form a normalized two +dimensional spectrum profile. This profile is then smoothed by fitting +one dimensional functions, "fit1d", along the lines or columns most closely +corresponding to the dispersion axis or a special two dimensional +function, "fit2d", described by Marsh (see \fBapprofile\fR). +.le +.ls clean = no +Detect and replace deviant pixels? +.le +.ls saturation = INDEF +Saturation or nonlinearity level. During variance weighted extractions +wavelength points having any pixels above this value are excluded from the +profile determination. +.le +.ls readnoise = 0. +Read out noise in photons. This parameter defines the minimum noise +sigma. It is defined in terms of photons (or electrons) and scales +to the data values through the gain parameter. A image header keyword +(case insensitive) may be specified to get the value from the image. +.le +.ls gain = 1 +Detector gain or conversion factor between photons/electrons and +data values. It is specified as the number of photons per data value. +A image header keyword (case insensitive) may be specified to get the value +from the image. +.le +.ls lsigma = 3., usigma = 3. +Lower and upper rejection thresholds, given as a number of times the +estimated sigma of a pixel, for cleaning. +.le + +The following parameters are used to fit the normalization spectrum using +the ICFIT routine. +.ls function = "legendre" +Fitting function for the normalization spectra. The choices are "legendre" +polynomial, "chebyshev" polynomial, linear spline ("spline1"), and +cubic spline ("spline3"). +.le +.ls order = 1 +Number of polynomial terms or number of spline pieces for the fitting function. +.le +.ls sample = "*" +Sample regions for fitting points. Intervals are separated by "," and an +interval may be one point or a range separated by ":". +.le +.ls naverage = 1 +Number of points within a sample interval to be subaveraged or submedianed to +form fitting points. Positive values are for averages and negative points +for medians. +.le +.ls niterate = 0 +Number of sigma clipping rejection iterations. +.le +.ls low_reject = 3. , high_reject = 3. +Lower and upper sigma clipping rejection threshold in units of sigma determined +from the RMS sigma of the data to the fit. +.le +.ls grow = 0. +Growing radius for rejected points (in pixels). That is, any rejected point +also rejects other points within this distance of the rejected point. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters from +\fBapdefault\fR, automatic aperture finding parameters from +\fBapfind\fR, recentering parameters from \fBaprecenter\fR, resizing +parameters from \fBapresize\fR, parameters used for centering and +editing the apertures from \fBapedit\fR, and tracing parameters from +\fBaptrace\fR. +.ih +DESCRIPTION +It is sometimes the case that it is undesirable to simply divide +two dimensional format spectra taken through fibers, aperture masks +with small apertures such as holes and slitlets, or small slits in +echelle formats by a flat field observation of a lamp. This is due +to the sharp dropoff of the flat field and object profiles and +absence of signal outside of the profile. Slight shifts or changes +in profile shape introduce bad edge effects, unsightly "grass" is +produced where there is no signal (which may also confuse extraction +programs), and the division will also remove the characteristic +profile of the object which might be needed for tracking the +statistical significance, variance weighted extraction, and more. +A straight flat field division also has the problem of changing the +shape of the spectrum in wavelength, again compromising the +poisson statistics and artificially boosting low signal regions. + +There are three approaches to consider. First, the +flat field correction can be done after extraction to one dimension. +This is valid provided the flat field and object profiles don't shift +much. However, for extractions that depend on a smooth profile, +such as the variance weighting algorithms of this package, the sensitivity +corrections must remain small; i.e. no large fringes or other +small scale variations that greatly perturb the true photon profile. +The second approach is to divide out the overall spectral shape of +the flat field spectrum, fill regions outside of the signal with +one and leave the profile shape intact. This will still cause profile +division problems described earlier but is mentioned here since it +implemented in a related task called \fBapnormalize\fR. The last +approach is to model both the profile and overall spectrum shape and +remove it from the flat field leaving only the sensitivity variations. +This is what the task \fBapflatten\fR does. + +The two dimensional flat field spectra within the defined apertures of +the input images are fit by a model having the profile of the data and +a smooth spectral shape. This model is then divided into the flat +field image within the aperture, replacing points of low signal, set +with the \fIthreshold\fR parameter, within the aperture and all points +outside the aperture by one to produce an output sensitivity variation +only flat field image. + +A two dimensional normalized profile is computed by dividing the data +within the aperture by the one dimensional spectrum and smoothing with +low order function fits parallel to the dispersion axis if the aperture +is well aligned with the axis or parallel to the traced aperture center +if the trace is tilted relative to the dispersion axis. The smooth +profile is then used to improve the spectrum estimate using variance +weighting and to eliminate deviant or cosmic ray pixels by sigma +tests. The profile algorithm is described in detail in +\fBapprofiles\fR and the variance weighted spectrum is described in +\fBapvariance\fR. + +The process of determining the profile and variance weighted spectrum, +and hence the two dimensional spectrum model, is identical to that used +for variance weighted extraction of the one dimensional spectra in the +tasks \fBapall\fR or \fBapsum\fR and in making a two dimensional +spectrum model in the task \fBapfit\fR. Most of the parameters in +this task are the same in those tasks and so further information about +them may be found in their descriptions. In fact, up to this point the +task is the same as \fBapfit\fR and, if the flat field were normalized +by this model it would produce the "ratio" output of that task. + +This task deviates from \fBapfit\fR in that the final variance weighted +one dimensional spectrum of the flat field is subjected to a smoothing +operation. This is done by fitting a function to the spectrum using +the \fBicfit\fR routine. This may be done interactively or +noninteractively depending on the \fBinteractive\fR parameter. The +default fitting parameters are part of this task. The goal of the +fitting is to follow the general spectral shape of the flat field light +(usually a lamp) but not the small bumps and wiggles which are the one +dimensional projection of sensitivity variations. When the fitted +function is multiplied into the normalize profile and then the two +dimensional model divided into the data the sensitivity variations not +part of the fitted spectrum are what is left in the final output flat +field. + +The remainder of this description covers the basic steps defining the +apertures to be used. These steps and parameter are much the same as +in any of the other \fBapextract\fR tasks. + +Aperture definitions may be inherited from those of other images by +specifying a reference image with the \fBreferences\fR parameter. +Images in the reference list are matched with those in the input list +in order. If the reference image list is shorter than the number of +input images, the last reference image is used for all remaining input +images. Thus, a single reference image may be given for all the input +images or different reference images may be given for each input +image. The special reference name "last" may be used to select the +last set apertures used in any of the \fBapextract\fR tasks. + +If an aperture reference image is not specified or no apertures are +found for the specified reference image, previously defined apertures +for the input image are sought in the aperture database. Note that +reference apertures supersede apertures for the input image. If no +apertures are defined they may be created automatically, the \fIfind\fR +option, or interactively in the aperture editor, if the +\fIinteractive\fR and \fIedit\fR options are set. + +The functions performed by the task are selected by a set of flag +parameters. The functions are an automatic spectrum finding and +aperture defining algorithm (see \fBapfind\fR) which is ignored if +apertures are already defined, automatic recentering and resizing +algorithms (see \fBaprecenter\fR and \fBapresize\fR), an interactive +aperture editing function (see \fBapedit\fR), a spectrum position tracing +and trace function fit (see \fBaptrace\fR), and the main function of +this task, the flat field profile and spectral shape modeling and removal. + +Each function selection will produce a query for each input spectrum if +the \fIinteractive\fR parameter is set. The queries are answered by +"yes", "no", "YES", or "NO", where the upper case responses suppress +the query for following images. There are other queries associated +with tracing which first ask whether the operation is to be done +interactively and, if yes, lead to queries for each aperture. If the +\fIinteractive\fR parameter is not set then aperture editing +interactive trace fitting, and interactive spectrum shape fitting are ignored. +.ih +REVISIONS +.ls APFLATTEN V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +EXAMPLES +1. To make a two dimensional flat field from a lamp observation: + +.nf + cl> apflatten fiber1 flat read=3 gain=1 back=fit + Yes find + No resize + No edit + Yes trace + Yes trace interactively + NO + Yes flatten + Yes fit interactively +.fi +.ih +SEE ALSO +apbackground, approfile, apvariance, apfit, icfit, +apdefault, apfind, aprecenter, apresize, apedit, aptrace, apsum +.endhelp diff --git a/noao/twodspec/apextract/doc/apmask.hlp b/noao/twodspec/apextract/doc/apmask.hlp new file mode 100644 index 00000000..78d775f9 --- /dev/null +++ b/noao/twodspec/apextract/doc/apmask.hlp @@ -0,0 +1,123 @@ +.help apmask Sep96 noao.twodspec.apextract +.ih +NAME +apmask -- Make pixel mask from apertures definitions +.ih +USAGE +apfind input +.ih +PARAMETERS +.ls input +List of input images with aperture definitions. +.le +.ls output +List of output mask names. As a convention the extension ".pl" (pixel +list) should be used. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and create a mask. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = no +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing is +disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database and the +parameter \fInfind\fR must be greater than zero. +.le +.ls recenter = no +Recenter the apertures? +.le +.ls resize = no +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace apertures? +.le +.ls fittrace = yes +Fit the traced points interactively? The \fIinteractive\fR parameter +must also be yes. +.le +.ls mask = yes +Create mask images? +.le + +.ls line = INDEF +The dispersion line (line or column perpendicular to the dispersion axis) to +be used in finding, recentering, resizing, editing, and starting to +trace spectra. A value of INDEF selects the middle of the image. +.le +.ls nsum = 1 +Number of dispersion lines to be summed or medianed. The lines are taken +around the specified dispersion line. A positive value takes the +sum and a negative value selects a median. +.le +.ls buffer = 0. +Buffer to add to aperture limits. One use for this is to increase +the width of the apertures when a mask is used to fit data between +the apertures. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters from +\fBapdefault\fR, automatic aperture finding parameters from +\fBapfind\fR, recentering parameters from \fBaprecenter\fR, resizing +parameters from \fBapresize\fR, parameters used for centering and +editing the apertures from \fBapedit\fR, and tracing parameters from +\fBaptrace\fR. +.ih +DESCRIPTION +Pixel list masks are created from the aperture definitions in the input +images. Pixel list masks are a compact way to define arbitrary +regions of an image. The masks may be used directly as an image with values +of 1 (in an aperture) and 0 (outside an aperture). Alternatively, +some tasks may use a mask to define regions to be operated upon. +When this task was written there were no such tasks though eventually +some tasks will be converted to use this general format. The intent +of making an aperture mask is to someday allow using it with the task +\fBimsurfit\fR to fit a background or scattered light surface. +(See \fBapscatter\fR for an alternative method). +.ih +EXAMPLES +1. To replace all data outside the apertures by zero: + +.nf + cl> apmask image image.pl nfind=10 + cl> imarith image * image.pl image1 +.fi +.ih +REVISIONS +.ls APMASK V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +SEE ALSO +apdefault, aprecenter, apresize, apedit, aptrace, apall +.endhelp diff --git a/noao/twodspec/apextract/doc/apnoise.hlp b/noao/twodspec/apextract/doc/apnoise.hlp new file mode 100644 index 00000000..a4f69f83 --- /dev/null +++ b/noao/twodspec/apextract/doc/apnoise.hlp @@ -0,0 +1,231 @@ +.help apnoise Sep96 noao.twodspec.apextract +.ih +NAME +apnoise -- Compute and examine noise characteristics of spectra +.ih +USAGE +apnoise input dmin dmax nbins +.ih +PARAMETERS +.ls input +List of input spectra to examine. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls dmin, dmax, nbins +The noise sigma is computed in a set of bins over the specified +range of image data numbers. +.le + +.ls interactive = yes +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing and trace +fitting are disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = yes +Recenter the apertures? +.le +.ls resize = yes +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace the apertures? +.le +.ls fittrace = yes +Interactively fit the traced positions by a function? The \fIinteractive\fR +parameter must also be yes. +.le + +.ls line = INDEF, nsum = 1 +The dispersion line (line or column perpendicular to the dispersion +axis) and number of adjacent lines (half before and half after unless +at the end of the image) used in finding, recentering, resizing, +and editing operations. For tracing this is the starting line and +the same number of lines are summed at each tracing point. A line of +INDEF selects the middle of the image along the dispersion axis. +A positive nsum sums the lines and a negative value takes the median. +However, for tracing only sums are allowed and the absolute value +is used. +.le +.ls threshold = 10. +Division threshold. If a pixel in the two dimensional normalization spectrum +is less than this value then a flat field value of 1 is output. +.le + +The following parameters control the profile and spectrum fitting. +.ls background = "none" +Type of background subtraction. The choices are "none" for no +background subtraction, "average" to average the background within the +background regions, or "fit" to fit across the dispersion using the +background within the background regions. Note that the "average" +option does not do any medianing or bad pixel checking; it is faster +than fitting however. Background subtraction also requires that the +background fitting parameters are properly defined. For the "average" +option only the background sample regions parameter is used. +.le +.ls pfit = "fit1d" (fit1d|fit2d) +Profile fitting algorithm to use with variance weighting or cleaning. +When determining a profile the two dimensional spectrum is divided by +an estimate of the one dimensional spectrum to form a normalized two +dimensional spectrum profile. This profile is then smoothed by fitting +one dimensional functions, "fit1d", along the lines or columns most closely +corresponding to the dispersion axis or a special two dimensional +function, "fit2d", described by Marsh (see \fBapprofile\fR). +.le +.ls clean = no +Detect and replace deviant pixels? +.le +.ls skybox = 1 +Box car smoothing length for sky background when using background +subtraction. Since the background noise is often the limiting factor +for good extraction one may box car smooth the sky to improve the +statistics in smooth background regions at the expense of distorting +the subtraction near spectral features. This is most appropriate when +the sky regions are limited due to a small slit length. +.le +.ls saturation = INDEF +Saturation or nonlinearity level. During variance weighted extractions +wavelength points having any pixels above this value are excluded from the +profile determination. +.le +.ls readnoise = "0." +Read out noise in photons. This parameter defines the minimum noise +sigma. It is defined in terms of photons (or electrons) and scales +to the data values through the gain parameter. A image header keyword +(case insensitive) may be specified to get the value from the image. +.le +.ls gain = "1." +Detector gain or conversion factor between photons/electrons and +data values. It is specified as the number of photons per data value. +A image header keyword (case insensitive) may be specified to get the value +from the image. +.le +.ls lsigma = 3., usigma = 3. +Lower and upper rejection thresholds, given as a number of times the +estimated sigma of a pixel, for cleaning. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters from +\fBapdefault\fR, automatic aperture finding parameters from +\fBapfind\fR, recentering parameters from \fBaprecenter\fR, resizing +parameters from \fBapresize\fR, parameters used for centering and +editing the apertures from \fBapedit\fR, and tracing parameters from +\fBaptrace\fR. +.ih +CURSOR COMMANDS +The following cursor keys and colon commands are available during the +display of the noise sigmas and noise model. See \fBapedit\fR for +the commands for that mode. + +.nf +? Print command help +q Quit +r Redraw +w Window the graph (see :/help) +I Interupt immediately + +:gain <value> Check or set the gain model parameter +:readnoise <value> Check or set the read noise model parameter + +Also see the CURSOR MODE commands (:.help) and the windowing commands +(:/help). +.fi +.ih +DESCRIPTION +\fBApnoise\fR computes the noise sigma as a function of data value +using the same profile model used for weighted extraction and +cosmic ray cleanning. In particular, the residuals used in computing the +noise sigma are the same as those during cleanning. By looking +at the noise sigma as a function of data value as compared to that +predicted by the noise model based on the read out noise and gain +parameters one can then better refine these values for proper +rejection of cosmic rays without rejection of valid data. +So this task can be used to check or deduce these values and also +to adjust them to include additional sources of error such as +flat field noise and, especially, an additional source of noise due +to the accuracy of the profile modeling. + +The first part of this task follows the standard model of allowing +one to define apertures by finding, recentering, editing, and +tracing. If one has previously defined apertures then these +steps can be skipped. Once the apertures are defined the apertures +are internally extracted using the profile modeling (see \fBapprofile\fR) +with the optional background subtraction, cleanning, and choices of +profile fitting algorithm, "fit1d" or "fit2d". But rather than +outputing the extracted spectrum as in \fBapsum\fR or \fBapall\fR +or various functions of the data and profile model as in \fBapfit\fR, +\fBapnormalize\fR, or \fBapflatten\fR, the task computes the +residuals for all points in all apertures (essentially the same +as the difference output of \fBapfit\fR) and determines the +sigma (population corrected RMS) as a function of model data value +in the specified bins. The bins are defined by a minimum and +maximum data value (found using \fBminmax\fR, \fBimplot\fR, or +\fBimexamine\fR) and the number of bins. + +The noise sigma values, with their estimated uncertainties, are then +plotted as a function of data numer. A curve representing the specified +read out noise and gain is also plotted. The user then has the +option of varying these two parameters with colon commands. The +aim of this is to find a noise model which either represents the +measure noise sigmas or at least exceeds them so that only valid +outliers such as cosmic rays will be rejected during cleanning. +The interactive graphical mode only has this function. The other +keys and colon commands are the standard ones for redrawing, windowing, +and quitting. +.ih +EXAMPLES +1. To check that the read noise and gain parameters are reasonable for +cleaning \fBapnoise\fR is run. In this case it is assumed that the +apertures have already been defined and traced. + +.nf + cl> minmax lsobj + lsobj -2.058870315551758 490.3247375488282 + cl> apnoise lsobj 0 500 50 rece- resi- edit- trace- + A graph of the noise sigma for data between 0 and 500 + data numbers is given with a line showing the + expected value for the current read noise and gain. + The read noise and gain may be varied if desired. + Exit with 'q' +.fi +.ih +REVISIONS +.ls APNOISE V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +SEE ALSO +apbackground, approfile, apvariance, apfit, icfit, minmax, +apdefault, apfind, aprecenter, apresize, apedit, aptrace, apsum +.endhelp diff --git a/noao/twodspec/apextract/doc/apnormalize.hlp b/noao/twodspec/apextract/doc/apnormalize.hlp new file mode 100644 index 00000000..fda3fd31 --- /dev/null +++ b/noao/twodspec/apextract/doc/apnormalize.hlp @@ -0,0 +1,324 @@ +.help apnormalize Sep96 noao.twodspec.apextract +.ih +NAME +apnormalize -- Normalize 2D apertures by 1D functions +.ih +USAGE +apnormalize input output +.ih +PARAMETERS +.ls input +List of input images to be normalized. +.le +.ls output +List of output image names for the normalized input images. If no output +name is given then the input name is used as a root with the extension +".norm" added. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and normalize. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = yes +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing and trace +fitting are disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = yes +Recenter the apertures? +.le +.ls resize = yes +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace the apertures? +.le +.ls fittrace = yes +Interactively fit the traced positions by a function? The \fIinteractive\fR +parameter must also be yes. +.le +.ls normalize = yes +Normalize the aperture spectra by a one dimensional function? +.le +.ls fitspec = yes +Fit normalization spectrum interactively? The \fIinteractive\fR +parameter must also be yes. +.le + +.ls line = INDEF, nsum = 1 +The dispersion line (line or column perpendicular to the dispersion +axis) and number of adjacent lines (half before and half after unless +at the end of the image) used in finding, recentering, resizing, +and editing operations. For tracing this is the starting line and +the same number of lines are summed at each tracing point. A line of +INDEF selects the middle of the image along the dispersion axis. +A negative nsum selects a median rather than a sum except that +tracing always uses a sum. +.le +.ls cennorm = no +Normalize to the aperture center rather than the mean? +.le +.ls threshold = 10. +All pixels in the normalization spectrum less than this value are replaced +by this value. +.le + +The following parameters control the normalization spectrum extraction. +.ls background = "none" +Type of background subtraction. The choices are "none" for no +background subtraction, "average" to average the background within the +background regions, or "fit" to fit across the dispersion using the +background within the background regions. Note that the "average" +option does not do any medianing or bad pixel checking; it is faster +than fitting however. Background subtraction also requires that the +background fitting parameters are properly defined. For the "average" +option only the background sample regions parameter is used. +.le +.ls weights = "none" +Type of extraction weighting. Note that if the \fIclean\fR parameter is +set then the weights used are "variance" regardless of the weights +specified by this parameter. The choices are: +.ls "none" +The pixels are summed without weights except for partial pixels at the +ends. +.le +.ls "variance" +The extraction is weighted by estimated variances of the pixels using +a poisson noise model. +.le +.le +.ls pfit = "fit1d" (fit1d|fit2d) +Profile fitting algorithm to use with variance weighting or cleaning. +When determining a profile the two dimensional spectrum is divided by +an estimate of the one dimensional spectrum to form a normalized two +dimensional spectrum profile. This profile is then smoothed by fitting +one dimensional functions, "fit1d", along the lines or columns most closely +corresponding to the dispersion axis or a special two dimensional +function, "fit2d", described by Marsh (see \fBapprofile\fR). +.le +.ls clean = no +Detect and replace deviant pixels? +.le +.ls skybox = 1 +Box car smoothing length for sky background when using background +subtraction. Since the background noise is often the limiting factor +for good extraction one may box car smooth the sky to improve the +statistics in smooth background regions at the expense of distorting +the subtraction near spectral features. This is most appropriate when +the sky regions are limited due to a small slit length. +.le +.ls saturation = INDEF +Saturation or nonlinearity level. During variance weighted extractions +wavelength points having any pixels above this value are excluded from the +profile determination. +.le +.ls readnoise = 0. +Read out noise in photons. This parameter defines the minimum noise +sigma. It is defined in terms of photons (or electrons) and scales +to the data values through the gain parameter. A image header keyword +(case insensitive) may be specified to get the value from the image. +.le +.ls gain = 1 +Detector gain or conversion factor between photons/electrons and +data values. It is specified as the number of photons per data value. +A image header keyword (case insensitive) may be specified to get the value +from the image. +.le +.ls lsigma = 3., usigma = 3. +Lower and upper rejection thresholds, given as a number of times the +estimated sigma of a pixel, for cleaning. +.le + +The following parameters are used to fit the normalization spectrum using +the ICFIT routine. +.ls function = "legendre" +Fitting function for the normalization spectra. The choices are "legendre" +polynomial, "chebyshev" polynomial, linear spline ("spline1"), and +cubic spline ("spline3"). +.le +.ls order = 1 +Number of polynomial terms or number of spline pieces for the fitting function. +.le +.ls sample = "*" +Sample regions for fitting points. Intervals are separated by "," and an +interval may be one point or a range separated by ":". +.le +.ls naverage = 1 +Number of points within a sample interval to be subaveraged or submedianed to +form fitting points. Positive values are for averages and negative points +for medians. +.le +.ls niterate = 0 +Number of sigma clipping rejection iterations. +.le +.ls low_reject = 3. , high_reject = 3. +Lower and upper sigma clipping rejection threshold in units of sigma determined +from the RMS sigma of the data to the fit. +.le +.ls grow = 0. +Growing radius for rejected points (in pixels). That is, any rejected point +also rejects other points within this distance of the rejected point. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters from +\fBapdefault\fR, automatic aperture finding parameters from +\fBapfind\fR, recentering parameters from \fBaprecenter\fR, resizing +parameters from \fBapresize\fR, parameters used for centering and +editing the apertures from \fBapedit\fR, and tracing parameters from +\fBaptrace\fR. +.ih +DESCRIPTION +For each image in the input image list the two dimensional spectra +defined by a set of apertures are normalized by a one dimensional +normalization function derived by extracting and smoothing the spectrum +by fitting a function with the \fBicfit\fR procedure. The value of the +fitting function at each point along the dispersion, divided by the +aperture width to form a mean or scaled to the same mean as the center +pixel of the aperture depending on the \fIcennorm\fR parameter, is +divided into the two dimensional input aperture. All points outside +the apertures are set to unity. + +The purpose of this task is to remove a general shape from the aperture +spectra. If low order (order = 1 for instance) functions are used then +only the amplitudes of the spectra are affected, shifting each aperture +to approximately unit intensity per pixel. If high order functions are +used only the small spatial scale variations are preserved. This +is useful for making flat field images with the spectral signature of the +continuum source removed or for producing two dimensional normalized +spectra similar to the task \fBonedspec.continuum\fR. For flat fields +this algorithm retains the profile shape which may be useful for +removing the profile response in short slit data. However, often +one does not want the profile of the flat fielded observation to be +modified in which case the task \fBapflatten\fR should be used. + +The normalization spectrum is first extracted in the same way as is +the one dimensional extraction in \fBapsum\fR or \fBapall\fR. In +particular the same parameters for selecting weighting and cleaning +are available. After extraction the spectrum is fit using the +\fBicfit\fR routine. This may be done interactively or noninteractively +depending on the \fIinteractive\fR parameter. The default fitting +parameters are part of this task. The goal of the fitting depends +on the application. One may be trying to simply continuum normalize, +in which case one wants to iteratively reject and grow the rejected +points to exclude the lines and fit the continuum with a +moderate order function (see \fBcontinuum\fR for more discussion). +If one wants to simply normalize all spectra to a common flux, say to +remove a blaze function in echelle data, then an order of 1 will +normalize by a constant. For flat field and profile correction of +small slits one wants to fit the large scale shape of the +spectrum but not fit the small bumps and wiggles due to sensitivity +variations and fringing. + +The smoothed extracted spectrum represents the total flux within the +aperture. There are two choices for scaling to a normalization per +pixel. One is to divide by the aperture width, thus computing an average +flux normalization. In this case the peak of the spectrum will be +greater than unity. This is done when \fIcennorm\fR = no. When this +parameter has the value yes then the mean of the normalization spectrum +is scaled to the mean of the aperture center, computed by linearly +interpolating the two pixels about the traced center. This will give +values near one for the pixels at the center of the aperture in the +final output image. + +Before division of each pixel by the appropriate dispersion point in +the normalization spectrum, all pixels below the value specified by the +\fIthreshold\fR parameter in the normalization spectrum are replaced by +the threshold value. This suppresses division by very small numbers. +Finally, the pixels within the aperture are divided by the normalization +function and the pixels outside the apertures are set to 1. + +The remainder of this description covers the basic steps defining the +apertures to be used. These steps and parameter are much the same as +in any of the other \fBapextract\fR tasks. + +Aperture definitions may be inherited from those of other images by +specifying a reference image with the \fBreferences\fR parameter. +Images in the reference list are matched with those in the input list +in order. If the reference image list is shorter than the number of +input images, the last reference image is used for all remaining input +images. Thus, a single reference image may be given for all the input +images or different reference images may be given for each input +image. The special reference name "last" may be used to select the +last set apertures used in any of the \fBapextract\fR tasks. + +If an aperture reference image is not specified or no apertures are +found for the specified reference image, previously defined apertures +for the input image are sought in the aperture database. Note that +reference apertures supersede apertures for the input image. If no +apertures are defined they may be created automatically, the \fIfind\fR +option, or interactively in the aperture editor, if the +\fIinteractive\fR and \fIedit\fR options are set. + +The functions performed by the task are selected by a set of flag +parameters. The functions are an automatic spectrum finding and +aperture defining algorithm (see \fBapfind\fR) which is ignored if +apertures are already defined, automatic recentering and resizing +algorithms (see \fBaprecenter\fR and \fBapresize\fR), an interactive +aperture editing function (see \fBapedit\fR), a spectrum position tracing +and trace function fit (see \fBaptrace\fR), and the main function of +this task, the one dimensional normalization of the aperture +profiles. + +Each function selection will produce a query for each input spectrum if +the \fIinteractive\fR parameter is set. The queries are answered by +"yes", "no", "YES", or "NO", where the upper case responses suppress +the query for following images. There are other queries associated +with tracing which first ask whether the operation is to be done +interactively and, if yes, lead to queries for each aperture. If the +\fIinteractive\fR parameter is not set then aperture editing, +interactive trace fitting, and interactive spectrum shape fitting are ignored. +.ih +EXAMPLES +To make a flat field image which leaves the total counts of the object +images approximately unchanged from a quartz echelle or slitlet image: + +.nf + cl> apnormalize qtz001,qtz002 flat001,flat002 + Yes find + No resize + No edit + Yes trace + Yes trace interactively + NO + Yes flatten + Yes fit interactively +.fi +.ih +REVISIONS +.ls APNORMALIZE V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +SEE ALSO +apbackground, approfile, apvariance, apfit, icfit, +apdefault, apfind, aprecenter, apresize, apedit, aptrace, apsum +.endhelp diff --git a/noao/twodspec/apextract/doc/approfiles.hlp b/noao/twodspec/apextract/doc/approfiles.hlp new file mode 100644 index 00000000..43ae774a --- /dev/null +++ b/noao/twodspec/apextract/doc/approfiles.hlp @@ -0,0 +1,131 @@ +.help approfiles Feb93 noao.twodspec.apextract + +.ce +Spectrum Profile Determinations + + +The foundation of variance weighted or optimal extraction, cosmic ray +detection and removal, two dimensional flat field normalization, and +spectrum fitting and modeling is the accurate determination of the +spectrum profile across the dispersion as a function of wavelength. +The previous version of the APEXTRACT package accomplished this by +averaging a specified number of profiles in the vicinity of each +wavelength after correcting for shifts in the center of the profile. +This technique was sensitive to perturbations from cosmic rays +and the exact choice of averaging parameters. The current version of +the package uses two different algorithm which are much more stable. + +The basic idea is to normalize each profile along the dispersion to +unit flux and then fit a low order function to sets of unsaturated +points at nearly the same point in the profile parallel to the +dispersion. The important point here is that points at the same +distance from the profile center should have the nearly the same values +once the continuum shape and spectral features have been divided out. +Any variations are due to slow changes in the shape of the profile with +wavelength, differences in the exact point on the profile, pixel +binning or sampling, and noise. Except for the noise, the variations +should be slow and a low order function smoothing over many points will +minimize the noise and be relatively insensitive to bad pixels such as +cosmic rays. Effects from bad pixels may be further eliminated by +chi-squared iteration and clipping. Since there will be many points +per degree of freedom in the fitting function the clipping may even be +quite aggressive without significantly affecting the profile +estimates. Effects from saturated pixels are minimized by excluding +from the profile determination any profiles containing one or more +saturated pixels as defined by the \fIsaturation\fR parameter. + +The normalization is, in fact, the one dimensional spectrum. Initially +this is the simple sum across the aperture which is then updated by the +variance weighted sum with deviant pixels possibly removed. This updated +one dimensional spectrum is what is meant by the profile normalization +factor in the discussion below. The two dimensional spectrum model or +estimate is the product of the normalization factor and the profile. This +model is used for estimating the pixel intensities and, thence, the +variances. + +There are two important requirements that must be met by the profile fitting +algorithm. First it is essential that the image data not be +interpolated. Any interpolation introduces correlated errors and +broadens cosmic rays to an extent that they may be confused with the +spectrum profile, particularly when the profile is narrow. This was +one of the problems limiting the shift and average method used +previously. The second requirement is that data fit by the smoothing +function vary slowly with wavelength. This is what precludes, for +instance, fitting profile functions across the dispersion since narrow, +marginally sampled profiles require a high order function using only a +very few points. One exception to this, which is sometimes useful but +of less generality, is methods which assume a model for the profile +shape such as a gaussian. In the methods used here there is no +assumption made about the underlying profile other than it vary +smoothly with wavelength. + +These requirements lead to two fitting algorithms which the user +selects with the \fIpfit\fR parameter. The primary method, "fit1d", +fits low order, one dimensional functions to the lines or columns +most nearly parallel to the dispersion. While this is intended for +spectra which are well aligned with the image axes, even fairly large +excursions or tilts can be adequately fit in this +way. When the spectra become strongly tilted then single lines or +columns may cross the actual profile relatively quickly causing the +requirement of a slow variation to be violated. One thought is to use +interpolation to fit points always at the same distance from the +profile. This is ruled out by the problems introduced by +image interpolation. However, there is a clever method which, in +effect, fits low order polynomials parallel to the direction defined by +tracing the spectrum but which does not interpolate the image data. +Instead it weights and couples polynomial coefficients. This +method was developed by Tom Marsh and is described in detail in the +paper, "The Extraction of Highly Distorted Spectra", PASP 101, 1032, +Nov. 1989. Here we refer to this method as the Marsh or "fit2d" +algorithm and do not attempt to explain it further. + +The choice of when to use the one dimensional or the two dimensional +fitting is left to the user. The "fit1d" algorithm is preferable since it +is faster, easier to understand, and has proved to be very robust. The +"fit2d" algorithm usually works just as well but is slower and has been +seen to fail on some data. The user may simply try both to achieve the +best results. + +What follows are some implementation details of the preceding ideas in the +APEXTRACT package. For column/line fitting, the fitting function is a +cubic spline. A base number of spline pieces is set by rounding up the +maximum trace excursion; an excursion of 1.2 pixels would use a spline of 2 +pieces. To this base number is added the number of coefficients in the +trace function in excess of two; i.e. the number of terms in excess of a +linear function. This is done because if the trace wiggles a large amount +then a higher order function will be needed to fit a line or column as the +profile shifts under it. Finally the number of pieces is doubled +because experience shows that for low tilts it doesn't matter but for +large tilts this improves the results dramatically. + +For the Marsh algorithm there are two parameters to be set, the +polynomial order parallel to the dispersion and the spacing between +parallel, coupled polynomials. The algorithm requires that the spacing +be less than a pixel to provide sufficient sampling. The spacing is +arbitrarily set at 0.95 pixels. Because the method always fits +polynomials to points at the same position of the profile the order +should be 1 except for variations in the profile shape with +wavelength. To allow for this the profile order is set at 10; i.e. a +9th order function. A final parameter in the algorithm is the number +of polynomials across the profile but this is obviously determined +from the polynomial spacing and the width of the aperture including an +extra pixel on either side. + +Both fitting algorithms weight the pixels by their variance as computed +from the background and background variance if background subtraction +is specified, the spectrum estimate from the profile and the spectrum +normalization, and the detector noise parameters. A poisson +plus constant gaussian readout noise model is used. The noise model is +described further in \fBapvariance\fR. + +As mentioned earlier, the profile fitting can be iterated to remove +deviant pixels. This is done by rejecting pixels greater than a +specified number of sigmas above or below the expected value based +on the profile, the normalization factor, the background, the +detector noise parameters, and the overall chi square of the residuals. +Rejected points are removed from the profile normalization and +from the fits. +.ih +SEE ALSO +apbackground apvariance apall apsum apfit apflatten +.endhelp diff --git a/noao/twodspec/apextract/doc/aprecenter.hlp b/noao/twodspec/apextract/doc/aprecenter.hlp new file mode 100644 index 00000000..5a05cb36 --- /dev/null +++ b/noao/twodspec/apextract/doc/aprecenter.hlp @@ -0,0 +1,148 @@ +.help aprecenter Sep96 noao.twodspec.apextract +.ih +NAME +aprecenter -- Recenter apertures automatically +.ih +USAGE +aprecenter input +.ih +PARAMETERS +.ls input +List of input images in which apertures are to be recentered. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le +.ls interactive = no +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing is +disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = yes +Recenter the apertures? +.le +.ls resize = no +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le + +.ls line = INDEF +The dispersion line (line or column perpendicular to the dispersion axis) to +be used in recentering the spectra. A value of INDEF selects the middle of the +image. +.le +.ls nsum = 1 +Number of dispersion lines to be summed or medianed. The lines are taken +around the specified dispersion line. A positive value takes a sum +and a negative values selects a median. +.le +.ls aprecenter = "" +List of apertures to be used in shift calculation. +.le +.ls npeaks = INDEF +Select the specified number of apertures with the highest peak values +to be recentered. If the number is INDEF all apertures will be selected. +If the value is less than 1 then the value is interpreted as a fraction +of total number of apertures. +.le +.ls shift = yes +Use the median shift from recentering the selected apertures to apply to +all apertures. The recentering is then a constant shift for all apertures. +The median is the average of the two central values for an even number +of apertures. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters are taken from the +task \fBapdefault\fR, automatic aperture finding parameters are taken +from \fBapfind\fR, and parameters used for centering and editing the +apertures are taken from \fBapedit\fR. + +When this operation is performed from the task \fBapall\fR all parameters +except the package parameters are included in that task. +.ih +DESCRIPTION +For each image in the input image list, the aperture center positions +are redefined by centering at the specified dispersion line using the +\fBcenter1d\fR algorithm with centering parameters from \fBapedit\fR. +Normally this is done when inheriting apertures from an aperture +reference image. The recentering does not change the "trace" of the +aperture but simple adds a shift across the dispersion axis. + +There are a several recentering options. Each selected aperture may be +recentered independently. However, if some or all of the spectra are +relatively weak this may actually be worse than using the reference +apertures defined by strong spectra or flat fields in the case of +fibers or aperture masks. One may select a subset of apertures to be +used in calculating shift. This is done with a the \fIaprecenter\fR +list of aperture numbers (see +\fBranges\fR for the syntax) and/or by selecting a specific number or +fraction of the apertures with the strongest peak values. The list +selection is done first and the strongest remaining apertures are used +to satisfy the \fBnpeaks\fR value. Though some or all of the apertures +may be recentered independently the most common case of recentering +reference apertures is to account for detector shifts. In this case +one expects that any shift should be common to all apertures. The +\fIshift\fR parameter allows using the new centers for all selected +apertures to compute a median shift to be added to ALL apertures. Using +a median shift for all apertures is the default. + +The \fIfind\fR parameter allows automatically finding apertures if none +are defined for the image or by a reference image. Since the purpose +of this task is to recenter reference apertures it is usually the case +that reference images are used and apertures are not defined by this +task. One case in which the apertures from the image itself might be +recentered is if one wants to use a different dispersion line. The +\fIresize\fR parameter may be used to adjust the widths in a variety +of ways based on the spectra profiles specific to each image. The +aperture positions and any other parameters may also be edited with the +aperture editing function if selected by the \fIapedit\fR parameter and +the task is run interactively. The recentering algorithm may be run +from the aperture editor using the 'g' keystroke. + +If the task is interactive the user is queried whether to perform +various steps on each image. The queries may be answered with one of +the four values "yes", "no", "YES" and "NO", where an upper case +response suppresses all further queries to this question. + +The aperture recentering algorithm may be selected from nearly every task +in the package. +.ih +EXAMPLES + cl> aprecenter newimage reference=flat +.ih +REVISIONS +.ls APRECENTER V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +SEE ALSO +center1d, ranges, apfind, apresize, apedit, apall +.endhelp diff --git a/noao/twodspec/apextract/doc/apresize.hlp b/noao/twodspec/apextract/doc/apresize.hlp new file mode 100644 index 00000000..d8ab4774 --- /dev/null +++ b/noao/twodspec/apextract/doc/apresize.hlp @@ -0,0 +1,201 @@ +.help apresize Sep96 noao.twodspec.apextract +.ih +NAME +apresize -- Resize apertures automatically +.ih +USAGE +apresize input +.ih +PARAMETERS +.ls input +List of input images in which apertures are to be resized. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = no +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing is +disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = no +Recenter the apertures? +.le +.ls resize = yes +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le + +.ls line = INDEF +The dispersion line (line or column perpendicular to the dispersion axis) to +be used in resizing the spectra. A value of INDEF selects the middle of the +image. +.le +.ls nsum = 1 +Number of dispersion lines to be summed or medianed. The lines are taken +around the specified dispersion line. A positive value takes a +sum and a negative value selects a median. +.le +.ls llimit = INDEF, ulimit = INDEF +Lower and upper aperture size limits. If the parameter \fIylevel\fR is +INDEF then these limits are assigned to all apertures. Otherwise +these parameters are used as limits to the resizing operation. +A value of INDEF places the aperture limits at the image edge (for the +dispersion line used). +.le +.ls ylevel = 0.1 +Data level at which to set aperture limits. If it is INDEF then the +aperture limits are set at the values given by the parameters +\fIllimit\fR and \fIulimit\fR. If it is not INDEF then it is a +fraction of the peak or an actual data level depending on the parameter +\fIpeak\fR. It may be relative to a local background or to zero +depending on the parameter \fIbkg\fR. +.le +.ls peak = yes +Is the data level specified by \fIylevel\fR a fraction of the peak? +.le +.ls bkg = yes +Subtract a simple background when interpreting the \fBylevel\fR parameter. +The background is a slope connecting the first minima +away from the aperture center. +.le +.ls r_grow = 0. +Change the lower and upper aperture limits by this fractional amount. +The factor is multiplied by each limit and the result added to limit. +.le +.ls avglimits = no +Apply the average lower and upper aperture limits to all apertures. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters are taken from the +task \fBapdefault\fR, automatic aperture finding parameters are taken +from \fBapfind\fR, and parameters used for centering and editing the +apertures are taken from \fBapedit\fR. + +When this operation is performed from the task \fBapall\fR all parameters +except the package parameters are included in that task. +.ih +DESCRIPTION +For each image in the input image list, the aperture limits are +redefined to be either specified values or by finding the points at +which the spectrum profile, linearly interpolated, first crosses a +specified value moving away from the aperture center at the specified +dispersion line. In the latter case the limits may then be increased +or decreased by a specified percentage, a maximum lower and upper limit, +may be imposed, and the independent limits may be averaged and the +single values applied to all the apertures. + +The simplest resizing choice is to reset all the aperture limits to +the values specified by \fIllimit\fR and \fIulimit\fR. This option +is selected if the parameter \fIylevel\fR is INDEF. + +There are several options for specifying a data level at which an +aperture is sized. The most common method (the default) is to specify +a fraction of the peak value since this is data independent and physically +reasonable. This is done by setting the fraction with the parameter +\fIylevel\fR and the parameter \fIpeak\fR to yes. If the peak parameter +is no then the level is a data value. + +The levels may be relative to zero, as might be used with fibers or +high dispersion / high signal-to-noise data, or relative to a local +linear background, as would be appropriate for slit data having a +significant background. A background is found and used if the +parameter \fIbkg\fR is set. The background determination is very +simple. Starting at the peak two background points are found, one in +each direction, which are inflection points; i.e. the first pixels +which are less than their two neighbors. A linear slope is fit and +subtracted for the purposes of measuring the peak and setting the +aperture limits. Note that if the slope is significant the actual +limits may not correspond to the intercepts of a line at constant data +value. + +Once aperture limits, a distance relative to the center, are determined +they are increased or decreased by a percentage, expressed as a fraction, +given by the parameter \fIr_grow\fR. To illustrate the operation, +if xlow is the initial lower limit then the final lower limit will be: + + xlow final = xlow * (1 + r_grow) + +A value of zero leaves the aperture limits unchanged. + +After the aperture limits are found, based on the above steps, a fixed lower +limit, given by the parameter \fIllimit\fR, is applied to the lower +aperture points and, similarly, a fixed upper limit is applied to the +upper aperture points. This feature protects against absurdly wide apertures. + +Finally, if the parameter \fIavglimits\fR is set the individual aperture +limits are averaged to form an average aperture. This average aperture +is then assigned to all apertures. This option allows keeping common +aperture sizes but allowing variation due to seeing changes. + +The resizing algorithm is available in the interactive aperture editor. +Here one may select individual apertures or all apertures using the +'a' switch. The resizing algorithm described above is selected using +the 'z' key. An simple alternative is the 'y' key which resizes +apertures to the y level marked by the cursor. + +If the task is interactive the user is queried whether to perform +various steps on each image. The queries may be answered with one of +the four values "yes", "no", "YES" and "NO", where an upper case +response suppresses all further queries to this question. + +The aperture resizing algorithm may be selected from nearly every task +in the package with the \fIresize\fR parameter. +.ih +EXAMPLES +1. To resize all apertures to the range -4 to 4: + + cl> apresize image llimit=-4 ulimit=4 ylevel=INDEF + +2. To resize all aperture to a point which is 5% of the peak relative +to a local background: + + cl> apresize image ylevel=.05 peak+ bkg+ + +3. To resize all apertures to the point where the data exceeds 100 +data units: + + cl> apresize image ylevel=100 peak- bkg- + +4. To resize all apertures to default values of the task except +averaging all the results at the end: + + cl> apresize image avg+ +.ih +REVISIONS +.ls APRESIZE V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +SEE ALSO +center1d, ranges, apfind, aprecenter, apedit, apall +.endhelp diff --git a/noao/twodspec/apextract/doc/apscatter.hlp b/noao/twodspec/apextract/doc/apscatter.hlp new file mode 100644 index 00000000..902c57a8 --- /dev/null +++ b/noao/twodspec/apextract/doc/apscatter.hlp @@ -0,0 +1,253 @@ +.help apscatter Sep96 noao.twodspec.apextract +.ih +NAME +apscatter -- Fit and subtract scattered light +.ih +USAGE +apscatter input output +.ih +PARAMETERS +.ls input +List of input images in which to determine and subtract scattered light. +.le +.ls output +List of output scattered light subtracted images. If no output images +are specified or the end of the output list is reached before the end +of the input list then the output image will overwrite the input image. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. All apertures are +used to define the scattered light region. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls scatter = "" +List of scattered light images. This is the scattered light subtracted +from the input image. If no list is given or the end of the list is +reached before the end of the input list then no scattered light image +is created. +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = yes +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing, trace +fitting, and interactive scattered light fitting are disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = yes +Recenter the apertures? +.le +.ls resize = yes +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace the apertures? +.le +.ls fittrace = yes +Interactively fit the traced positions by a function? The \fIinteractive\fR +parameter must also be yes. +.le +.ls subtract = yes +Subtract the scattered light from the input images? +.le +.ls smooth = yes +Smooth the cross-dispersion fits along the dispersion? +.le +.ls fitscatter = yes +Fit the scattered light across the dispersion interactively? +The \fIinteractive\fR parameter must also be yes. +.le +.ls fitsmooth = yes +Smooth the cross-dispersion fits along the dispersion? +The \fIinteractive\fR parameter must also be yes. +.le + +.ls line = INDEF, nsum = 1 +The dispersion line (line or column perpendicular to the dispersion +axis) and number of adjacent lines (half before and half after unless +at the end of the image) used in finding, recentering, resizing, +and editing operations. For tracing this is the starting line and +the same number of lines are summed at each tracing point. This is +also the initial line for interactive fitting of the scattered light. +A line of INDEF selects the middle of the image along the dispersion +axis. A positive nsum takes a sum and a negative value selects a +median except that tracing always uses a sum. +.le + +.ls buffer = 1. +Buffer distance from the aperture edges to be excluded in selecting the +scattered light pixels to be used. +.le +.ls apscat1 = "" +Fitting parameters across the dispersion. This references an additional +set of parameters for the ICFIT package. The default is the "apscat1" +parameter set. See below for additional information. +.le +.ls apscat2 = "" +Fitting parameters along the dispersion. This references an additional +set of parameters for the ICFIT package. The default is the "apscat2" +parameter set. See below for additional information. +.le +.ih +ICFIT PARAMETERS FOR FITTING THE SCATTERED LIGHT +There are two additional parameter sets which define the parameters used +for fitting the scattered light across the dispersion and along the +dispersion. The default parameter sets are \fBapscat1\fR and \fBapscat2\fR. +The parameters may be examined and edited by either typing their names +or by typing ":e" when editing the main parameter set with \fBeparam\fR +and with the cursor pointing at the appropriate parameter set name. +These parameters are used by the ICFIT package and a further +description may be found there. + +.ls function = "spline3" (apscat1 and apscat2) +Fitting function for the scattered light across and along the dispersion. +The choices are "legendre" polynomial, "chebyshev" polynomial, +linear spline ("spline1"), and cubic spline ("spline3"). +.le +.ls order = 1 (apscat1 and apscat2) +Number of polynomial terms or number of spline pieces for the fitting function. +.le +.ls sample = "*" (apscat1 and apscat2) +Sample regions for fitting points. Intervals are separated by "," and an +interval may be one point or a range separated by ":". +.le +.ls naverage = 1 (apscat1 and apscat2) +Number of points within a sample interval to be subaveraged or submedianed to +form fitting points. Positive values are for averages and negative points +for medians. +.le +.ls niterate = 5 (apscat1), niterate = 0 (apscat2) +Number of sigma clipping rejection iterations. +.le +.ls low_reject = 5. (apscat1) , low_reject = 3. (apscat2) +Lower sigma clipping rejection threshold in units of sigma determined +from the RMS sigma of the data to the fit. +.le +.ls high_reject = 2. (apscat1) , high_reject = 3. (apscat2) +High sigma clipping rejection threshold in units of sigma determined +from the RMS sigma of the data to the fit. +.le +.ls grow = 0. (apscat1 and apscat2) +Growing radius for rejected points (in pixels). That is, any rejected point +also rejects other points within this distance of the rejected point. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters from +\fBapdefault\fR, automatic aperture finding parameters from +\fBapfind\fR, recentering parameters from \fBaprecenter\fR, resizing +parameters from \fBapresize\fR, parameters used for centering and +editing the apertures from \fBapedit\fR, and tracing parameters from +\fBaptrace\fR. +.ih +DESCRIPTION +The scattered light outside the apertures defining the two dimensional +spectra is extracted, smoothed, and subtracted from each input image. The +approach is to first select the pixels outside the defined apertures +and outside a buffer distance from the edge of any aperture at each +point along the dispersion independently. A one dimensional function +is fit using the \fBicfit\fR package. This fitting uses an iterative +algorithm to further reject high values and thus fit the minima between +the spectra. (This even works reasonably well if no apertures are +defined). Because each fit is done independently the scattered light +thus determined will not be smooth along the dispersion. If desired +each line along the dispersion in the scattered light surface may then +be smoothed by again fitting a one dimensional function using the +\fBicfit\fR package. The final scattered light surface is then +subtracted from the input image to form the output image. The +scattered light surface may be output if desired. + +The reason for using two one dimensional fits as opposed to a surface fit +is that the actual shape of the scattered light is often not easily modeled +by a simple two dimensional function. Also the one dimensional function +fitting offers more flexibility in defining functions and options as +provided by the \fBicfit\fR package. + +The organization of the task is like the other tasks in the package +which has options for defining apertures using a reference image, +defining apertures through an automatic finding algorithm (see +\fBapfind\fR), automatically recentering or resizing the apertures (see +\fBaprecenter\fR and \fBapresize\fR), interactively editing the +apertures (see \fBapedit\fR), and tracing the positions of the spectra +as a function of dispersion position (see \fBaptrace\fR). Though +unlikely, the actual scattered light subtraction operation may be +suppressed when the parameter \fIsubtract\fR is no. If the scattered +light determination and fitting is done interactively (the +\fIinteractive\fR parameter set to yes) then the user is queried +whether or not to do the fitting and subtraction for each image. The +responses are "yes", "no", "YES", or "NO", where the upper case +queries suppress this query for the following images. When the task is +interactive there are further queries for each step of the operation +which may also be answered both individually or collectively for all +other input images using the four responses. + +When the scattered light operation is done interactively the user may +set the fitting parameters for the scattered light functions both +across and along the dispersion interactively. Initially the central +line or column is used but after exiting (with 'q') a prompt is given +for selecting additional lines or columns and for changing the buffer +distance. Note that the point of the interactive stage is to set the +fitting parameters. When the entire image is finally fit the last set +of fitting parameters are used for all lines or columns. + +The default fitting parameters are organized as separate parameter sets +called \fBapscat1\fR for the first fits across the dispersion and +\fBapscat2\fR for the second smoothing fits along the dispersion. +Changes to these parameters made interactively during execution of +this task are updated in the parameter sets. The general idea for +these parameters is that when fitting the pixels from between the +apertures the iteration and rejection thresholds are set to eliminate +high values while for smoothing along the dispersion a simple smooth +function is all that is required. +.ih +EXAMPLES +1. To subtract the scattered light from a set of images to form a +new set of images: + + cl> apscatter raw* %raw%new%* + +This example uses a substitution in the names from raw to new. +By default this would be done interactively + +2. To subtract the scattered light in place and save the scattered light +images: + + cl> apscatter im* "" scatter="s//im*" ref=im1 interact- + +The prefix s is added to the original names for the scattered light. +This operation is done noninteractively using a reference spectrum +to define the apertures. +.ih +REVISIONS +.ls APSCATTER V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +SEE ALSO +apfind, aprecenter, apresize, apedit, aptrace, apsum, apmask, icfit +.endhelp diff --git a/noao/twodspec/apextract/doc/apsum.hlp b/noao/twodspec/apextract/doc/apsum.hlp new file mode 100644 index 00000000..6fa7ad0e --- /dev/null +++ b/noao/twodspec/apextract/doc/apsum.hlp @@ -0,0 +1,402 @@ +.help apsum Sep96 noao.twodspec.apextract +.ih +NAME +apsum -- Extract one dimensional sums across the apertures +.ih +USAGE +apsum input +.ih +PARAMETERS +.ls input +List of input images containing apertures to be extracted. +.le +.ls output = "" +List of output rootnames for the extracted spectra. If the null +string is given or the end of the output list is reached before the end +of the input list then the input image name is used as the output rootname. +This will not conflict with the input image since an aperture number +extension is added for onedspec format, the extension ".ms" for multispec +format, or the extension ".ec" for echelle format. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls format = "multispec" (onedspec|multispec|echelle|strip) +Format for output extracted spectra. "Onedspec" format extracts each +aperture to a separate image while "multispec" and "echelle" extract +multiple apertures for the same image to a single output image. +The "multispec" and "echelle" format selections differ only in the +extension added. The "strip" format produces a separate 2D image in +which each column or line along the dispersion axis is shifted to +exactly align the aperture based on the trace information. +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le +.ls profiles = "" +List of profile images for variance weighting or cleanning. If variance +weighting or cleanning a profile of each aperture is computed from the +input image unless a profile image is specified, in which case the +profile is computed from the profile image. The profile image must +have the same dimensions and dispersion and it is assumed that the +spectra have the same position and profile shape as in the object +spectra. Use of a profile image is generally not required even for +faint input spectra but the option is available for those who wish +to use it. +.le + +.ls interactive = yes +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing, trace +fitting, and extraction review are disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = no +Recenter the apertures? +.le +.ls resize = no +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace the apertures? +.le +.ls fittrace = yes +Interactively fit the traced positions by a function? The \fIinteractive\fR +parameter must also be yes. +.le +.ls extract = yes +Extract the one dimensional aperture sums? +.le +.ls extras = no +Extract the raw spectrum (if variance weighting is used), the sky spectrum +(if background subtraction is used), and variance spectrum (if variance +weighting is used)? This information is extracted to the third dimension +of the output image. +.le +.ls review = yes +Review the extracted spectra? The \fIinteractive\fR parameter must also be +yes. +.le + +.ls line = INDEF, nsum = 10 +The dispersion line (line or column perpendicular to the dispersion +axis) and number of adjacent lines (half before and half after unless +at the end of the image) used in finding, recentering, resizing, +and editing operations. For tracing this is the starting line and +the same number of lines are summed at each tracing point. A line of +INDEF selects the middle of the image along the dispersion axis. +A positive nsum takes a sum while a negative value selects a median +except that tracing always uses a sum. +.le + +.ls background = "none" (none|average|median|minimum|fit) +Type of background subtraction. The choices are "none" for no background +subtraction, "average" to average the background within the background +regions, "median" to use the median in the background regions, "minimum" to +use the minimum in the background regions, or "fit" to fit across the +dispersion using the background within the background regions. Note that +the "average" option does not do any medianing or bad pixel checking, +something which is recommended. The fitting option is slower than the +other options and requires additional fitting parameter. +.le +.ls weights = "none" +Type of extraction weighting. Note that if the \fIclean\fR parameter is +set then the weights used are "variance" regardless of the weights +specified by this parameter. The choices are: +.ls "none" +The pixels are summed without weights except for partial pixels at the +ends. +.le +.ls "variance" +The extraction is weighted by the variance based on the data values +and a poisson/ccd model using the \fIgain\fR and \fIreadnoise\fR +parameters. +.le +.le +.ls pfit = "fit1d" (fit1d|fit2d) +Profile fitting algorithm to use with variance weighting or cleaning. +When determining a profile the two dimensional spectrum is divided by +an estimate of the one dimensional spectrum to form a normalized two +dimensional spectrum profile. This profile is then smoothed by fitting +one dimensional functions, "fit1d", along the lines or columns most closely +corresponding to the dispersion axis or a special two dimensional +function, "fit2d", described by Marsh (see \fBapprofile\fR). +.le +.ls clean = no +Detect and replace deviant pixels? +.le +.ls skybox = 1 +Box car smoothing length for sky background when using background +subtraction. Since the background noise is often the limiting factor +for good extraction one may box car smooth the sky to improve the +statistics in smooth background regions at the expense of distorting +the subtraction near spectral features. This is most appropriate when +the sky regions are limited due to a small slit length. +.le +.ls saturation = INDEF +Saturation or nonlinearity level in data units. During variance weighted +extractions wavelength points having any pixels above this value are +excluded from the profile determination and the sigma spectrum extraction +output, if selected by the \fIextras\fR parameter, flags wavelengths with +saturated pixels with a negative sigma. +.le +.ls readnoise = 0. +Read out noise in photons. This parameter defines the minimum noise +sigma. It is defined in terms of photons (or electrons) and scales +to the data values through the gain parameter. A image header keyword +(case insensitive) may be specified to get the value from the image. +.le +.ls gain = 1 +Detector gain or conversion factor between photons/electrons and +data values. It is specified as the number of photons per data value. +A image header keyword (case insensitive) may be specified to get the value +from the image. +.le +.ls lsigma = 4., usigma = 4. +Lower and upper rejection thresholds, given as a number of times the +estimated sigma of a pixel, for cleaning. +.le +.ls nsubaps = 1 +During extraction it is possible to equally divide the apertures into +this number of subapertures. For multispec format all subapertures will +be in the same file with aperture numbers of 1000*(subap-1)+ap where +subap is the subaperture (1 to nsubaps) and ap is the main aperture +number. For echelle format there will be a separate echelle format +image containing the same subaperture from each order. The name +will have the subaperture number appended. For onedspec format +each subaperture will be in a separate file with extensions and +aperture numbers as in the multispec format. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters from +\fBapdefault\fR, automatic aperture finding parameters from +\fBapfind\fR, recentering parameters from \fBaprecenter\fR, resizing +parameters from \fBapresize\fR, parameters used for centering and +editing the apertures from \fBapedit\fR, and tracing parameters from +\fBaptrace\fR. + +When this operation is performed from the task \fBapall\fR all +parameters except the package parameters are included in that task. +.ih +DESCRIPTION +For each image in the input image list, the two dimensional spectra are +extracted to one dimensional spectra by summing the pixels across the +dispersion axis at each wavelength along the dispersion axis within a +set of defined apertures. The extraction apertures consist of an +aperture number, a beam number, a title, a center, limits relative to +the center, a curve describing shifts of the aperture center across the +dispersion axis as a function of the wavelength, and parameters for +background fitting and subtraction. See \fBapextract\fR for a more +detailed discussion of the aperture structures. + +The extracted spectra are recorded in one, two, or three dimensional +images depending on the \fIformat\fR and \fIextras\fR parameters. The +output image rootnames are specified by the \fIoutput\fR list. If the +list is empty or shorter than the input list the missing names are +taken to be the same as the input image names. Because the rootnames +have extensions added it is common to default to the input names in +order to preserve a naming relation between the input two dimensional +spectra and the extracted spectra. + +When the parameter \fIextras\fR=no only the extracted spectra are +output. If the format parameter \fIformat\fR="onedspec" the output +aperture extractions are one dimensional images with names formed from +the output rootname and a numeric extension given by the aperture +number; i.e. root.0001 for aperture 1. Note that there will be as many +output images as there are apertures for each input image, all with the +same output rootname but with different aperture extensions. The +aperture beam number associated with each aperture is recorded in the +output image under the keyword BEAM-NUM. The output image name format +and the BEAM-NUM entry in the image are chosen to be compatible with +the \fBonedspec\fR package. + +If the format parameter is "echelle" or "multispec" the output aperture +extractions are put into a two dimensional image with a name formed from +the output rootname and the extension ".ech" or ".ms". Each line in +the output image corresponds to one aperture. Thus in this format +there is one output image for each input image. These are the preferred +output formats for reasons of compactness and ease of handling. These +formats are compatible with the \fBonedspec\fR, \fBechelle\fR, and +\fBmsred\fR packages. The relation between the line and the aperture +numbers is given by the header parameter APNUMn where n is the line and +the value is the aperture number and other numeric information. + +If the \fIextras\fR parameter is set to yes then the above formats +become three dimensional. Each plane in the third dimension contains +associated information for the spectra in the first plane. If variance +weighted extractions are done the unweighted spectra are recorded. If +background subtraction is done the background spectra are recorded. If +variance weighted extractions are done the sigma spectrum (the +estimated sigma of each spectrum pixel based on the individual +variances of the pixels summed) is recorded. The order of the +additional information is as given above. For example, an unweighted +extraction with background subtraction will have one additional plane +containing the sky spectra while a variance weighted extraction with +background subtractions will have the variance weighted spectra, the +unweighted spectra, the background spectra, and the sigma spectra in +consecutive planes. + +Aperture definitions may be inherited from those of other images by +specifying a reference image with the \fBreferences\fR parameter. +Images in the reference list are matched with those in the +input list in order. If the reference image list is shorter than the +number of input images, the last reference image is used for all +remaining input images. Thus, a single reference image may be given +for all the input images or different reference images may be given for +each input image. The special reference name "last" may be used to +select the last set apertures used in any of the \fBapextract\fR tasks. + +If an aperture reference image is not specified or no apertures are +found for the specified reference image, previously defined apertures +for the input image are sought in the aperture database. Note that +reference apertures supersede apertures for the input image. If no +apertures are defined they may be created automatically, the \fIfind\fR +option, or interactively in the aperture editor, if the +\fIinteractive\fR and \fIedit\fR options are set. + +The functions performed by the task are selected by a set of flag +parameters. The functions are an automatic spectrum finding and +aperture defining algorithm (see \fBapfind\fR) which is ignored if +apertures are already defined, automatic recentering and resizing +algorithms (see \fBaprecenter\fR and \fBapresize\fR), an interactive +aperture editing function (see \fBapedit\fR), a spectrum position tracing +and trace function fit (see \fBaptrace\fR), and the main function of +this task, one dimensional spectrum extraction. + +Each function selection will produce a query for each input spectrum if +the \fIinteractive\fR parameter is set. The queries are answered by +"yes", "no", "YES", or "NO", where the upper case responses suppress +the query for following images. There are other queries associated +with tracing and extracted spectrum review which first ask whether the +operation is to be done interactively and, if yes, lead to queries for +each aperture. The cursor keys available during spectrum review are +minimal, only the CURSOR MODE keys for expanding and adjusting the +graph are available and the quit key 'q'. If the \fIinteractive\fR +parameter is not set then aperture editing, interactive trace fitting, +and spectrum review are ignored. + +Background sky subtraction is done during the extraction based on +background regions and parameters defined by the default parameters or +changed during the interactive setting of the apertures. The background +subtraction options are to do no background subtraction, subtract the +average, median, or minimum of the pixels in the background regions, or to +fit a function and subtract the function from under the extracted object +pixels. The background regions are specified in pixels from +the aperture center and follow changes in center of the spectrum along the +dispersion. The syntax is colon separated ranges with multiple ranges +separated by a comma or space. The background fitting uses the \fBicfit\fR +routines which include medians, iterative rejection of deviant points, and +a choice of function types and orders. Note that it is important to use a +method which rejects cosmic rays such as using either medians over all the +background regions (\fIbackground\fR = "median") or median samples during +fitting (\fIb_naverage\fR < -1). The background subtraction algorithm and +options are described in greater detail in \fBapsum\fR and +\fBapbackground\fR. + +Since the background noise is often the limiting factor for good +extraction one may box car smooth the sky to improve the statistics in +smooth background regions at the expense of distorting the subtraction +near spectra features. This is most appropriate when the sky region is +limited due to small slit length. The smoothing length is specified by +the parameter \fIskybox\fR. + +For a more extended discussion about the background determination see +\fBapbackground\fR. + +The aperture extractions consists of summing all the background +subtracted pixel values at a given wavelength within the aperture +limits. The aperture limits form a fixed width aperture but the center +varies smoothly to follow changes in the position of the spectrum +across the dispersion axis. At the ends of the aperture partial pixels +are used. + +The pixels in the sum may be weighted as specified by the \fIweights\fR +parameter. If the weights parameter is "none" and the \fIclean\fR +parameter is no then the simple sum of the pixels (with fractional +endpoints) is extracted. If the weights parameter is "variance" or if +the \fBclean\fR parameter is yes the pixels are weighted by their +estimated variance derived from a noise model based on the \fIgain\fR +and \fIreadnoise\fR parameters and a smooth profile function. Normally +the profile function is determined from the data being extracted. +However, one may substitute a "profile" image as specified by the +\fIprofiles\fR parameter for computing the profile. This requires that +the profile image have spectra of identical position and profile as +the image being extracted. For example, this would likely be the case +with fiber spectra and an off-telescope spectrograph and a strong flat +field or object spectrum could be used for weak spectra. Note that +experience has shown that even for very weak spectra there is little +improvement with using a separate profile image but the user is free +to experiment. + +When the \fIclean\fR parameter is set pixels deviating by more than a +specified number of sigma from the profile function are excluded from the +variance weighted sum. Note that the \fIclean\fR parameter always selects +variance weights. For a more complete discussion of the extraction sums, +variance weighting, cleaning, the noise model, and profile function +determination see \fBapvariance\fR and \fBapprofiles\fR. +.ih +EXAMPLES +1. To simply extract the spectra from a multislit observation: + + cl> apsum multislit1 + +The positions of the slits are defined using either automatic finding +or with the aperture editor. The positions of the slits are traced if +necessary and then the apertures are extracted to the image +"multslit1.ms". The steps of defining the slit positions and tracing +can be done as part of this command or previously using the other tasks +in the \fBapextract\fR package. +.ih +REVISIONS +.ls APSUM V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". + +The "nsubaps" parameter now allows onedspec and echelle output formats. +The echelle format is appropriate for treating each subaperture as +a full echelle extraction. + +The dispersion axis parameter was moved to purely a package parameter. + +As a final step when computing a weighted/cleaned spectrum the total +fluxes from the weighted spectrum and the simple unweighted spectrum +(excluding any deviant and saturated pixels) are computed and a +"bias" factor of the ratio of the two fluxes is multiplied into +the weighted spectrum and the sigma estimate. This makes the total +fluxes the same. In this version the bias factor is recorded in the logfile +if one is kept. Also a check is made for unusual bias factors. +If the two fluxes disagree by more than a factor of two a warning +is given on the standard output and the logfile with the individual +total fluxes as well as the bias factor. If the bias factor is +negative a warning is also given and no bias factor is applied. +In the previous version a negative (inverted) spectrum would result. +.le +.ih +SEE ALSO +apbackground, apvariance, approfile, +apdefault, apfind, aprecenter, apresize, apedit, aptrace, apall +.endhelp diff --git a/noao/twodspec/apextract/doc/aptrace.hlp b/noao/twodspec/apextract/doc/aptrace.hlp new file mode 100644 index 00000000..3b9ddd38 --- /dev/null +++ b/noao/twodspec/apextract/doc/aptrace.hlp @@ -0,0 +1,354 @@ +.help aptrace Sep96 noao.twodspec.apextract +.ih +NAME +aptrace -- Trace spectra for aperture extraction +.ih +USAGE +.nf +aptrace images +.fi +.ih +PARAMETERS +.ls input +List of input images to be traced. +.le +.ls apertures = "" +Apertures to recenter, resize, trace, and extract. This only applies +to apertures read from the input or reference database. Any new +apertures defined with the automatic finding algorithm or interactively +are always selected. The syntax is a list comma separated ranges +where a range can be a single aperture number, a hyphen separated +range of aperture numbers, or a range with a step specified by "x<step>"; +for example, "1,3-5,9-12x2". +.le +.ls references = "" +List of reference images to be used to define apertures for the input +images. When a reference image is given it supersedes apertures +previously defined for the input image. The list may be null, "", or +any number of images less than or equal to the list of input images. +There are three special words which may be used in place of an image +name. The word "last" refers to the last set of apertures written to +the database. The word "OLD" requires that an entry exist +and the word "NEW" requires that the entry not exist for each input image. +.le + +.ls interactive = yes +Run this task interactively? If the task is not run interactively then +all user queries are suppressed and interactive aperture editing and trace +fitting are disabled. +.le +.ls find = yes +Find the spectra and define apertures automatically? In order for +spectra to be found automatically there must be no apertures for the +input image or reference image defined in the database. +.le +.ls recenter = no +Recenter the apertures? +.le +.ls resize = yes +Resize the apertures? +.le +.ls edit = yes +Edit the apertures? The \fIinteractive\fR parameter must also be yes. +.le +.ls trace = yes +Trace the apertures? +.le +.ls fittrace = yes +Interactively fit the traced positions by a function? The \fIinteractive\fR +parameter must also be yes. +.le + +.ls line = INDEF, nsum = 1 +The dispersion line (line or column perpendicular to the dispersion +axis) and number of adjacent lines (half before and half after unless +at the end of the image) used in finding, recentering, resizing, +and editing operations. For tracing this is the starting line and +the same number of lines are summed at each tracing point. A line of +INDEF selects the middle of the image along the dispersion axis. +A positive nsum selects the number of lines to sum while a negative +value selects a median. Tracing always uses a sum. +.le +.ls step = 10 +Step along the dispersion axis between determination of the spectrum +positions. +.le +.ls nlost = 3 +Number of consecutive steps in which the profile is lost before quitting +the tracing in one direction. To force tracing to continue through +regions of very low signal this parameter can be made large. Note, +however, that noise may drag the trace away before it recovers. +.le + +The following parameters are the defaults used to fit the traced positions +by a function of the dispersion line. These parameters are those used by +the ICFIT package. +.ls function = "legendre" +Default trace fitting function. The fitting function types are +"chebyshev" polynomial, "legendre" polynomial, "spline1" linear spline, and +"spline3" cubic spline. +.le +.ls order = 2 +Default trace function order. The order refers to the number of +terms in the polynomial functions or the number of spline pieces in the spline +functions. +.le +.ls sample = "*" +Default fitting sample. The sample is given by a set of colon separated +ranges each separated by either whitespace or commas. The string "*" refers +to all points. +.le +.ls naverage = 1 +Default number of points to average or median. Positive numbers +average that number of sequential points to form a fitting point. +Negative numbers median that number, in absolute value, of sequential +points. A value of 1 does no averaging and each data point is used in the +.le +.ls niterate = 0 +Default number of rejection iterations. If greater than zero the fit is +used to detect deviant traced positions and reject them before repeating the +fit. The number of iterations of this process is given by this parameter. +.le +.ls low_reject = 3., high_reject = 3. +Default lower and upper rejection sigma. If greater than zero traced +points deviating from the fit below and above the fit by more than this +number of times the sigma of the residuals are rejected before refitting. +.le +.ls grow = 0. +Default reject growing radius. Traced points within a distance given by this +parameter of any rejected point are also rejected. +.le +.ih +ADDITIONAL PARAMETERS +I/O parameters and the default dispersion axis are taken from the +package parameters, the default aperture parameters from +\fBapdefault\fR, automatic aperture finding parameters from +\fBapfind\fR, recentering parameters from \fBaprecenter\fR, resizing +parameters from \fBapresize\fR, and parameters used for centering and +editing the apertures from \fBapedit\fR. + +When this operation is performed from the task \fBapall\fR all parameters +except the package parameters are included in that task. +.ih +DESCRIPTION +For each image in the input image list the position of the spectrum +within each aperture are determined at a number of points along the +dispersion axis and a smooth function is fit to these positions. The +fitted curve defines a shift to be added to the aperture center at each +wavelength. Other options allow defining apertures using a reference +image, defining apertures through an automatic finding algorithm (see +\fBapfind\fR), automatically recentering apertures (see +\fBaprecenter\fR), automatically resizing apertures (see +\fBapresize\fR), and interactively editing the apertures prior to +tracing (see \fBapedit\fR). Tracing is selected with the parameter +\fItrace\fR. If the tracing is done interactively (the +\fIinteractive\fR parameter set to yes) then the user is queried +whether or not to trace each image. The responses are "yes", "no", +"YES", or "NO", where the upper case queries suppress this query +for the following images. + +The tracing begins with the specified dispersion line. A dispersion +line is a line or column of the image perpendicular to the dispersion +axis. The dispersion axis is defined in the image header or by the +package parameter \fIdispaxis\fR. If the starting dispersion line is +INDEF then the middle dispersion line of the image is used. The +positions of the spectra are determined using the \fBcenter1d\fR +algorithm and the centering parameters from the \fBapedit\fR task. +(See help under \fBcenter1d\fR for a description of the one dimensional +position measuring algorithm.) The positions are redetermined at other +points along the dispersion axis by stepping from the starting line in +steps specified by the user. A number of dispersion lines around each +dispersion line to be measured may be summed to improve the position +determinations, particularly for weak profiles. This number usually is +set equal to the tracing step. + +It is important to understand how to set the step size and the +relationship between the step size and the centering error radius. +Larger steps reduce the computational time, which is an important +consideration. However, if the step is too large then the tracing may +fail to follow the systematic changes in the positions of the +spectrum. The centering error radius, \fIradius\fR, is used to limit +the maximum position change between two successive steps. If the +positions of a spectrum changes by more than the specified amount or +the data contrast falls below the \fIthreshold\fR parameter then +the position is marked as lost. + +The centering radius should be large enough to follow changes in the +spectrum positions from point to point but small enough to detect an error +in the tracing by a sudden abrupt change in position, such as caused by +crowding with other spectra or by the disappearance of the spectrum. The +\fInlost\fR parameter determines how many consecutive steps the position +may fail to be found before tracing in that direction is stopped. If this +parameter is small the trace will stop quickly upon loss of the profile +while if it is very large it will continue to try and recover the profile. + +The parameter \fIthreshold\fR checks for the vanishing of a spectrum by +requiring a minimum range in the data used for centering. If the +tracing fails when the spectra are strong and well defined the problem +is usually that the step size is too large and/or the centering error +radius is too small. + +The traced positions of a spectrum include some measurement variation +from point to point. Since the actual position of the spectrum in the +image should be a smooth curve, a function of the dispersion line is fit +to the measured points. The fitted function is stored as part of the +aperture description. It is an offset to be added to the aperture's +center as a function of the dispersion line. Even if the fitting is not +done interactively plots of the trace and the fit are recorded in the +plot file or device specified by the parameter \fIplotfile\fR. + +Fitting the traced spectrum positions with a smooth function may be +performed interactively when parameters \fIfittrace\fR and +\fIinteractive\fR are yes. This allows changing the default fitting +parameters. The function fitting is done with the interactive curve +fitting tools described under the help topic \fBicfit\fR. There are +two levels of queries when fitting the spectrum positions +interactively; prompts for each image and prompts for each aperture in +an image. These prompts may be answered individually with the lower +case responses "yes" or "no" or answered for all further prompts with +the responses "YES" or "NO". Responding with "yes" or "YES" to the +image prompt allows interactive fitting of the traced positions for the +spectra. Prompts are then given for each aperture in the image. When +an spectrum is not fit interactively the last set of fitting parameters +are used (initially the default function and order given by the task +parameters). Note that answering "YES" or "NO" to a aperture prompt +applies to all further aperture in the current image only. Responding +with "no" or "NO" to the image prompt fits the spectrum positions for +all apertures in all images with the last set of fitting parameters. + +The tracing may also be done from the interactive aperture editor with +the 't' key. The aperture tracing algorithm may be selected from many +of the tasks in the package with the \fItrace\fR parameter. +.ih +APTRACE DATABASE COEFFICIENTS +The path of an aperture is described by a function that gives an additive +offset relative to the aperture center as stored under the database keyword +center. The function is saved in the database as a series of +coefficients. The section containing the coefficients starts with the +keyword "curve" and the number of coefficients. + +The first four coefficients define the type of function, the order +or number of spline pieces, and the range of the independent variable +(the line or column coordinate along the dispersion). The first +coefficient is the function type code with values: + +.nf + Code Type + 1 Chebyshev polynomial + 2 Legendre polynomial + 3 Cubic spline + 4 Linear spline +.fi + +The second coefficient is the order (actually the number of terms) of +the polynomial or the number of pieces in the spline. + +The next two coefficients are the range of the independent variable over +which the function is defined. These values are used to normalize the +input variable to the range -1 to 1 in the polynomial functions. If the +independent variable is x and the normalized variable is n, then + +.nf + n = (2 * x - (xmax + xmin)) / (xmax - xmin) +.fi + +where xmin and xmax are the two coefficients. + +The spline functions divide the range into the specified number of +pieces. A spline coordinate s and the nearest integer below s, +denoted as j, are defined by + +.nf + s = (x - xmin) / (xmax - xmin) * npieces + j = integer part of s +.fi + +where npieces are the number of pieces. + +The remaining coefficients are those for the appropriate function. +The number of coefficients is either the same as the function order +for the polynomials, npieces+1 for the linear spline, or npieces + 3 +for the cubic spline. + +1. Chebyshev Polynomial + +The polynomial can be expressed as the sum + +.nf + y = sum from i=1 to order {c_i * z_i} +.fi + +where the c_i are the coefficients and the z_i are defined +interactively as: + +.nf + z_1 = 1 + z_2 = n + z_i = 2 * n * z_{i-1} - z_{i-2} +.fi + +2. Legendre Polynomial + +The polynomial can be expressed as the sum + +.nf + y = sum from i=1 to order {c_i * z_i} +.fi + +where the c_i are the coefficients and the z_i are defined +interactively as: + +.nf + z_1 = 1 + z_2 = n + z_i = ((2*i-3) * n * z_{i-1} - (i-2) * z_{i-2}) / (i - 1) +.fi + +3. Linear Spline + +The linear spline is evaluated as + +.nf + y = c_j * a + c_{j+1} * b +.fi + +where j is as defined earlier and a and b are fractional difference +between s and the nearest integers above and below + +.nf + a = (j + 1) - s + b = s - j +.fi + +4. Cubic Spline + +The cubic spline is evaluated as + +.nf + y = sum from i=0 to 3 {c_{i+j} * z_i} +.fi + +where j is as defined earlier. The term z_i are computed from +a and b, as defined earlier, as follows + +.nf + z_0 = a**3 + z_1 = 1 + 3 * a * (1 + a * b) + z_2 = 1 + 3 * b * (1 + a * b) + z_3 = b**3 +.fi +.ih +EXAMPLES +.ih +REVISIONS +.ls APTRACE V2.11 +The "apertures" parameter can be used to select apertures for resizing, +recentering, tracing, and extraction. This parameter name was previously +used for selecting apertures in the recentering algorithm. The new +parameter name for this is now "aprecenter". +.le +.ih +SEE ALSO +apdefault, apfind, aprecenter, apresize, apedit, apall, +center1d, icfit, gtools +.endhelp diff --git a/noao/twodspec/apextract/doc/apvariance.hlp b/noao/twodspec/apextract/doc/apvariance.hlp new file mode 100644 index 00000000..6ff1e073 --- /dev/null +++ b/noao/twodspec/apextract/doc/apvariance.hlp @@ -0,0 +1,159 @@ +.help apvariance Aug90 noao.twodspec.apextract + +.ce +Variance Weighted and Cleaned Extractions + + +There are two types of aperture extraction (estimating the background +subtracted flux across a fixed width aperture at each image line or +column) in the APEXTRACT package. One is a simple sum of pixel values +across an aperture. It is selected by specifying "none" for the +\fIweights\fR parameter. The second type weights each pixel in the sum +by it's estimated variance based on a spectrum model and detector noise +parameters. This type of extraction is selected by specifying +"variance" for the weighting parameter. These two extractions are +defined by the following equations. + +.nf + none: S = sum { I - B } + variance: S = sum { (P**2 / V) (I - B) / P } / sum { P**2 / V } +.fi + +S is the one dimensional spectrum flux at a particular wavelength (line +or column along the dispersion axis). The sum is over all pixels at +that wavelength within the aperture limits. If the aperture endpoints +occupy only a fraction of a pixel then the pixel value above the +background is multiplied by the fraction. I is the pixel value and B +is the estimated background at that pixel (see \fBapbackground\fR), P +is estimated normalized profile value for that pixel (see +\fBapprofile\fR), and V is the estimated variance of the pixel based on +the noise model described below. Note that the quantity (I-B)/P is an +independent estimate of the total flux from one pixel since the +integral of P is one and it is these estimates that are variance +weighted. + +Variance weighting is often called "optimal" extraction since it +produces the best unbiased signal-to-noise estimate of the flux in the +two dimensional profile. The theory and application of this type of +weighting has been described in several papers. The ones which were +closely examined and used as a model for the algorithms in this +software are "An Optimal Extraction Algorithm for CCD Spectroscopy", +PASP 98, 609, 1986, by Keith Horne and "The Extraction of Highly +Distorted Spectra", PASP 100, 1032, 1989, by Tom Marsh. + +The noise model for the image data used in the variance weighting, +cleaning, and profile fitting consists of a constant gaussian noise and +a photon count dependent poisson noise. The signal is related to the +number of photons detected in a pixel by a \fRgain\fR parameter given +as the number of photons per data number. The gaussian noise is given +by a \fIreadnoise\fR parameter which is a defined as a sigma in +photons. The poisson noise is approximated as gaussian with sigma +given by the number of photons. + +Some additional effects which should be considered in principle, and +which are possibly important in practice, are that the variance +estimate should be based on the actual number of photons detected before +correction for pixel sensitivity; i.e. before flat field correction. +Furthermore the uncertainty in the flat field should also be included +in the weighting. However, the profile must be determined free of +sensitivity effects including rapid larger scale variations such as +fringing. Thus, ideally one should input the unflat-fielded +observation and the flat field data and carry out the extractions with +the above points in mind. However, due to the complexity often +involved in basic CCD reductions and special steps required for +producing spectroscopic flat fields this level of sophistication is not +provided by the current package. The package does provide, however, +for propagation of an approximate uncertainty in the background +estimate when using background subtraction. + +The noise model is described by the following equations. + +.nf + (1) V = max (VMIN, (R**2 + I + VB) / G**2) + max (VMIN, (R**2 + S * P + B + VB) / G**2) + + (2) VB = 0. if (B = 0) + = B / (N - 1) if (B > 0) + + (3) VMIN = 1 / G**2 if (R = 0) + R**2 / G**2 if (R > 0) +.fi + +V is the desired variance of a pixel to use for variance weighting. R +is the photon read out noise specified by the parameter \fIreadnoise\fR +and G is the photon per data value gain specified by the parameter +\fIgain\fR. There are two forms to (1). The first is used in the +initial pass of estimating the spectrum flux S and the actual pixel +value I (which includes any background) is used for the poisson term. +The other form is used in a second pass (and further passes if +cleaning) using the estimated data value based on the normalized +profile P scaled to the estimated total flux plus the estimated +background B; i.e. I estimated = S * P + B. + +The background variance VB is computed using the poisson noise model +based on the estimated background counts. If no background subtraction +is done then both B and VB are set to zero. If a background is +determined the background is either an average or function fit to +pixels in defined background regions. If a fit is used B need not be a +constant. Because the background estimate is based on a finite number of +pixels, the poisson variance estimate is divided by the number N (minus +one) of pixels used in determining the background. The number of +pixels used includes any box car smoothing. Thus, the larger the +number of background pixels the smaller the background noise +contribution to the variance weighting. This method is only +approximate since no correction is made for the number of degrees of +freedom and correlations when using the fitting method of background +estimation. + +VMIN is a minimum variance need to avoid generating zero or negative +variances from the data. The definition of VMIN is such that if a zero +read out noise is specified (which is certainly possible such as with +photon counting detectors) then a minimum of 1 photon is imposed. +Otherwise the minimum is set by the read out noise even if the poisson +count part is (unphysically) negative. + +One deviation from the linear photon response mode which is considered +is saturation. A data level specified by the parameter +\fIsaturation\fR is used to exclude data from the profile fitting. +During extraction the saturated pixels are not treated any differently +than unsaturated pixels except that dispersion points with saturated +pixels are flagged by reversing the sign of the final estimated sigma; +the sigma output is enabled with the \fIextras\fR parameter. Exclusion +of saturated pixels from the extraction, as is done with deviant +pixels, was tried but this resulted in higher noise in the spectrum. + +If removal of cosmic rays and other deviant pixels is desired, called +cleaning and selected with a \fIclean\fR parameter, they are +iteratively rejected based on the estimated variance and excluded from +the weighted sum. Note that a cleaned extraction is always variance +weighted regardless of the value of the \fIweights\fR parameter. This +makes sense since the detector noise parameters must be specified and +the spectrum profile computed, so all of the computational effort must +be done anyway, and the variance weighting is as good or superior to a +simple unweighted extraction. + +The detection and removal of deviant pixels is straightforward. Based +on the noise model described earlier, pixels deviating by more than a +specified number of sigma (square root of the variance) above or below +the model are removed from the weighted sum. A new spectrum estimate +is made and the rejection is repeated. The rejections are made one at +a time starting with the most deviant and up to half the pixels in the +aperture may be rejected. The total number of rejected pixels in the +spectrum is recorded in the logfile and a profile plot of data and +model profile is recorded in the plotfile. + +As a final step when computing a weighted/cleaned spectrum the total +fluxes from the weighted spectrum and the simple unweighted spectrum +(excluding any deviant and saturated pixels) are computed and a +"bias" factor of the ratio of the two fluxes is multiplied into +the weighted spectrum and the sigma estimate. This makes the total +fluxes the same. The bias factor is recorded in the logfile +if one is kept. Also a check is made for unusual bias factors. +If the two fluxes disagree by more than a factor of two a warning +is given on the standard output and the logfile with the individual +total fluxes as well as the bias factor. If the bias factor is +negative a warning is also given and no bias factor is applied. +.ih +SEE ALSO +apbackground approfiles apall apsum +.endhelp diff --git a/noao/twodspec/apextract/doc/dictionary b/noao/twodspec/apextract/doc/dictionary new file mode 100644 index 00000000..1046499c --- /dev/null +++ b/noao/twodspec/apextract/doc/dictionary @@ -0,0 +1,282 @@ +ADU +APALL +APAXIS +APEDIT +APEXTRACT +APFIND +APFIT +APFLATTEN +APFORMAT +APID +APID2 +APIO +APMASK +APNORMALIZE +APNUM2 +APNUMn +APPARAMS +APRECENTER +APRESIZE +APSCATTER +APSTRIP +APSUM +APTRACE +CCD +CL +DISPAXIS +ECHELLE +EOF +EPARAM +FIT1D +FLAT1D +Fri +Horne +Horne's +ICFIT +IMARITH +IMREPLACE +IMSURFIT +INDEF +IRAF +Jul +Jul90 +Nfind +P.O +PASP +PSET +RMS +SETDISP +SN +STDIN +STDOUT +Slitlet +VB +VMIN +Valdes +ansclob +ansclobber +ansclobber1 +ansdbwr +ansdbwrite +ansdbwrite1 +ansedit +ansextr +ansextract +ansfind +ansfit +ansfits +ansfitscatter +ansfitsmooth +ansfitspec +ansfitspec1 +ansfitt +ansfittrace +ansfittrace1 +ansflat +ansmask +ansnorm +ansrece +ansrecenter +ansresi +ansresize +ansrevi +ansreview +ansreview1 +ansscat +anssmoo +anssmooth +anstrac +anstrace +ap +apall +apall1 +apbackground +apdefault +apdefault.apidtable +apdefault.b +apdefault.lower +apdefault.upper +apdemo1d +apdemo2d +apdemo2d.ms +apdemos +apdemosdb +apedit +apedit.radius +apedit.threshold +apedit.width +apertur +apextract +apextractsys +apfind +apfind.maxsep +apfind.minsep +apfind.nfind +apfind.order +apfit +apfit1 +apflat1 +apflatten +apidtab +apidtable +apio +aplast +apmask +apnorm1 +apnormalize +apparams +approfile +approfiles +aprecenter +aprecenter.apertures +aprecenter.npeaks +aprecenter.shift +apresize +apresize.avglimits +apresize.bkg +apresize.llimit +apresize.peak +apresize.r +apresize.ulimit +apresize.ylevel +apscat1 +apscat2 +apscatter +apscript +apstrip +apsum +apsum.background +apsum.clean +apsum.extras +apsum.gain +apsum.lsigma +apsum.nsubaps +apsum.readnoise +apsum.saturation +apsum.skybox +apsum.usigma +apsum.weights +aptrace +aptrace.function +aptrace.grow +aptrace.high +aptrace.low +aptrace.naverage +aptrace.niterate +aptrace.nsum +aptrace.order +aptrace.sample +aptrace.step +apvariance +artdata +avg +avglimi +avglimits +backgro +bkg +ccd +cennorm +center1d +chebyshev +cl +clopset +computerese +curfit +dbwrite +dispaxi +dispaxis +dropoff +ech +ech001 +echelle +echelles +elp +eparam +fiber1 +fitscatter +fitsmooth +fitspec +fittrace +fittype +flat001,flat002 +funct +gaussian +gkimosaic +gtools +icfit +im +im1 +image.pl +image1 +imarith +imh +imred +imred.generic.flat1d +imsurfit +keystroke +legendre +llimit +logfile +longslit +lparam +ls1 +lsigma +maxsep +maxtilt +minsep +mk1dspec +mk2dspec +mknoise +msred +multislit1 +multspec.ms +naverage +ndhelp +nessie +newimage +nfind +niter +niterat +niterate +nl +noao.twodspec.apextract +npeaks +nsubaps +nsum +onedspec +onedspec.continuum +pl +plotfile +poisson +polyord +polysep +pset +psets +qtz001,qtz002 +rdnoise +readnoi +readnoise +rec +ref +res +root.0001 +rootname +rootnames +sampl +saturat +setdisp +skybox +slitlet +slitlets +spline1 +spline3 +thresho +twodspec +ulimit +usigma +whitespace +widt +xlow +xmax +xmin +ylevel diff --git a/noao/twodspec/apextract/doc/old/Tutorial.hlp b/noao/twodspec/apextract/doc/old/Tutorial.hlp new file mode 100644 index 00000000..fd0ff8e8 --- /dev/null +++ b/noao/twodspec/apextract/doc/old/Tutorial.hlp @@ -0,0 +1,278 @@ +.help Tutorial Sep86 "Apextract Tutorial" +.ih +TOPICS +The APEXTRACT tutorial consists of a number of topics. The topics are brief +and describe the simplest operations. More sophisticated discussions are +available for the tasks in the printed documentation and through the on-line +\fBhelp\fR facility; i.e. "help taskname". To obtain information +on a particular topic type "tutor topic" where the topic is one of the +following: + +.nf + TOPICS + + topics - List of topics + overview - An overview of the \fBapextract\fR tasks + organization - How the package is organized + apertures - Definition of apertures + defining - How to define apertures + references - Using reference images to define apertures + queries - Description of interactive queries + cosmic - Problems with cosmic ray removal + all - Print all of this tutorial +.fi +.ih +OVERVIEW +The \fBapextract\fR tasks extract spectra from two dimensional images. +One image axis is the dispersion axis and the other image axis is the +aperture axis. The user defines apertures whose position along the +aperture axis is a function of position along the dispersion axis and +whose width is fixed. There are two types of aperture extractions. +\fIStrip\fR extraction produces two dimensional images in which the +center of the aperture is exactly centered along one of the lines or +columns of the image and the edges of the image just include the +edges of the aperture. \fISum\fR extraction sums the pixels across +the aperture at each point along the dispersion to produce a one +dimensional spectrum. The extraction algorithms include +fitting and subtracting a background, modeling the profiles across the +dispersion, detecting and removing deviant pixels which do not fit the +model profiles, and weighting the pixels in the sum extraction according +to the signal-to-noise. + +To extract spectra one must define the dispersion axis by placing the +parameter DISPAXIS in the image headers using the task \fBsetdisp\fR. +Then apertures are defined either automatically, interactively, or by +reference to an image in which apertures have been previously defined. +Initially the apertures are aligned parallel to the dispersion axis +but if the spectra are not aligned with the dispersion axis and have +profiles which can be traced then the position of the aperture along +the aperture axis can be made a function of position along the dispersion +axis. Finally, the extraction operation is performed for each aperture. +.ih +ORGANIZATION +The tasks in the \fBapextract\fR package are highly integrated. This +means that tasks call each other. For example, the aperture +editing task may be called from the finding, tracing, or extraction +tasks. Also from within the aperture editor the finding, tracing, and +extraction tasks may be run on selected apertures. This organization +provides the flexibility to process images either step-by-step, +image-by-image, or very interactively from the aperture editor. For +example, one may defined apertures for all the images, trace all the +images, and then extract all the images or, alternatively, define, +trace, and extract each image individually. + +This organization also implies that parameters from many tasks are used +during the execution of a single task. For example, the editing +parameters are used in any of the tasks which may enter the interactive +editing task. Two tasks, \fBapio\fR and \fBapdefault\fR, only set +parameters but these parameters are package parameters which affect all +the other tasks. There are two effects of this parameter +organization. First, only parameters from the task being executed may +be specified on the command line or with menu mode. However, the +parameters are logically organized and the parameter list for any +particular task is not excessively long or complex. For example, the +number of parameters potentially used by the task \fBapsum\fR is 57 +parameters instead of just the parameters logically related to the +extraction itself. + +Another feature of the package organization is the ability to +control the flow and interactivity of the tasks. The parameter +\fIinteractive\fR selects whether the user will be queried about various +operations and if the aperture editor, trace fitting, and extraction +review will be performed. The parameters \fBdbwrite, +find, recenter, edit, trace, fittrace, sum, review\fR, and +\fBstrip\fR select which operations may be performed by a particular +task. When a task is run interactively the user is queried about +whether to perform each operation on each image. A query may be answered +individually or as a group. In the latter case the query will not be +repeated for other images but will always take the specified action. +This allows the user to begin interactively and then reduce +the interactivity as the images are processed and parameters are refined. +For additional discussion of these parameters see the topic QUERIES. + +Finally, the package has attempted to provide good logging facilities. +There are log files for both time stamped text output and plots. +The text log is still minimal but the plot logging is complete +and allows later browsing and hardcopy review of batch processing. +See \fBapio\fR for further discussion. + +This package organization is somewhat experimental. Let us know what +you think. +.ih +APERTURES +An aperture consists of the following elements: + +.ls id +An integer aperture identification number. The identification number +must be unique. The aperture number is used as the default extension +of the extracted spectra. +.le +.ls beam +An integer beam number. The beam number need not be unique; i.e. +several apertures may have the same beam number. The beam number will +be recorded in the image header of the extracted spectrum. Note that +the \fBonedspec\fR package restricts the beam numbers to the range 0 to +49. +.le +.ls cslit, cdisp +The center of the aperture along the slit and dispersion axes in the two +dimensional image. +.le +.ls lslit, ldisp +The lower limits of the aperture, relative to the aperture center, +along the slit and dispersion axes. The lower limits need not be less +than the center. +.le +.ls uslit, udisp +The upper limits of the aperture, relative to the aperture center, +along the slit and dispersion axes. The upper limits need not be greater +than the center. +.le +.ls curve +An shift to be added to the center position for the slit axis which is +a function of position along the dispersion axis. The function is one +of the standard IRAF \fBicfit\fR types; a legendre polynomial, a chebyshev +polynomial, a linear spline, or a cubic spline. +.le +.ls background +Background fitting parameters used by the \fBicfit\fR package for background +subtraction. Background parameters need not be used if background +subtraction is not needed. The background sample regions are specified +relative to aperture center. +.le + +The aperture center is the only absolute coordinate relative to the +image or image section. The size and shape of the aperture are +specified relative to the aperture center. The center and aperture +limits in image coordinates along the slit axis are functions of the +dispersion coordinate, lambda, given by + +.nf + center(lambda) = cslit + curve(lambda) + lower(lambda) = center(lambda) + lslit + upper(lambda) = center(lambda) + uslit +.fi + +Note that both the lower and upper constants are added to the center +defined by the aperture center and the curve offset. The aperture limits +along the dispersion axis are constant, + +.nf + center(s) = cdisp + lower(s) = center(s) + ldisp + upper(s) = center(s) + udisp +.fi + +Usually the aperture size along the dispersion is equal to the entire image. +.ih +DEFINING APERTURES +If a reference image is specified the \fBapextract\fR tasks first search +the database for it's apertures. Note that this supercedes any apertures +previously defined for the input image. If no reference apertures are +found then the apertures for the input image are sought. +If no apertures are defined at this point then apertures +may be defined automatically, interactively, or, by default, in the center +of the image. The automatic method, \fBapfind\fR, locates spectra as peaks +across the dispersion and then defines default apertures given by the +parameters from \fBapdefault\fR. The algorithm is controlled +by specifying the number of apertures and a minimum separation between +spectra. Only the strongest peaks are selected. + +The interactive method, \fBapedit\fR, allows the user to mark the positions +of apertures and to adjust the aperture parameters such as the limits. +The aperture editor may be used edit apertures defined by any of the +other methods. + +If no apertures are defined when tracing or extraction is begun, that is +following the optional editing, then a default aperture is defined +centered along the aperture axis of the image. This ultimate default +may be useful for spectra defined by image sections; i.e. the image +section is a type of aperture. Image sections are sometimes used with +multislit spectra. +.ih +REFERENCE IMAGES +The \fBapextract\fR tasks define apertures for an input image by +first searching the database for apertures recorded under the name +of the reference image. Use of a reference image implies +superceding the input image apertures. Reference images are specified +by an image list which is paired with +the input image list. If the number of reference images +is less than the number of input images then the last reference image +is used for all following images. Generally, the reference image list +consists of the null string if reference images are not to be used, +a single image which is applied to all input images, or a list +which exactly matches the input list. The special reference image +name "last" may be used to refer to the last apertures written to +the database; usually the previous input image. + +The task parameter \fIrecenter\fR specifies whether the +reference apertures are to be recentered on the spectra in the input +image. If recentering is desired the \fBcenter1d\fR centering algorithm +is used with centering parameters taken from the task \fBapedit\fR. +The spectra in the image must all have well defined profiles for the +centering. It does not make sense to center an aperture defined for +a region of sky or background or for an arc spectrum. + +Recentering is used when the only change between two spectra is +a shift along the aperture axis. This can reduce the number of +images which must be traced if tracing is required by using a +traced reference image and just recentering on the next spectra. +Recentering of a traced reference image is also useful when +the spectra are too weak to be traced reliably. Recentering would be +most commonly used with echelle or multiaperture spectra. + +Recentering is not used when extracting sky or arc calibration spectra +from long slit or multislit images. This is because it is desirable +to extract from the same part of the detector as the object spectra and +because recentering does not make sense when there is no profile across +the aperture. Centering or recentering is also not used when dealing +with apertures covering parts of extended objects in long slit spectra. +.ih +QUERIES +When the interactive parameter is specified as yes in a task then the user +is queried at each step of the task. The queries refer to either a +particular image or a particular aperture in an image. The acceptable +responses to the queries are the strings "yes", "no", "YES", and "NO". +The lower case answers refer only to the specific query. The upper +case answers apply to all repetitions of query for other images and +apertures. The upper case reponses then suppress the query and take +the specified action every time. This allows tasks to be highly interactive +by querying at each step and for each image or to skip or perform +each step for all images without queries. + +The two steps of fitting a function to traced positions and reviewing +one dimensional extracted spectra, selected with the parameters +\fIaptrace.fittrace\fR and \fIapsum.review\fR have two levels of queries. +First a query is made for the image being traced or extracted. If +the answer is "yes" or "YES" then a query is made for each aperture. +A response of "YES" or "NO" applies only to the remaining apertures +and not to apertures of a later image. +.ih +COSMIC RAYS +The cleaning and modeling features available during aperture extraction +are fairly good. They are described in the documentation for the +tasks. It can only go so far towards discriminating cosmic rays +because of problems described below. Further work on the algorithm may +improve the performance but it is best, when feasible, to first +eliminate at least the strongest cosmic rays from the data before +extracting. One recommended method is to use \fBlineclean\fR with a +high rejection threshold and a high order. + +There are two difficult problems encountered in using the +\fBapextract\fR tasks for cosmic ray detection. First, the spectral +profiles are first interpolated to a common center before comparison +with the average profile model. The interpolation often splits single +strong spikes into two high points of half the intensity, as is +intuitively obvious. Furthermore, for very strong spikes there is +ringing in the interpolator which makes the interpolated profile depart +significantly from the original profile. The fact that the +interpolated profile now has two or more deviant points makes it much +harder to decide which points are in the profile. This leads to the +second problem. The average profile model is scaled to fit the +spectrum profile. When there are several high points it is very +difficult to discriminate between a higher scale factor and bad +points. The algorithm has been enhanced to initially exclude the point which +most pulls the scale factor to higher values. If there are two high +points due to the interpolator splitting a strong spike then this helps +but does not eliminate errors in the extracted spectra. +.endhelp diff --git a/noao/twodspec/apextract/doc/old/apextract.ms b/noao/twodspec/apextract/doc/old/apextract.ms new file mode 100644 index 00000000..3e71890b --- /dev/null +++ b/noao/twodspec/apextract/doc/old/apextract.ms @@ -0,0 +1,725 @@ +.EQ +delim $$ +define sl '{s lambda}' +.EN +.RP +.TL +The IRAF APEXTRACT Package +.AU +Francisco Valdes +.AI +IRAF Group - Central Computer Services +.K2 +P.O. Box 26732, Tucson, Arizona 85726 +.AB +The IRAF \fBapextract\fR package provides tools for the extraction of +one and two dimensional spectra from two dimensional images +such as echelle, long slit, multi-fiber, and multi-slit spectra. +Apertures of fixed width along the spatial define the regions of +the two dimensional images to be extracted at each point along the +dispersion axis. Apertures may follow changes in the positions of +the spectra as a function of position along the dispersion axis. +The spatial and dispersion axes may be oriented along either image axis. +Extraction to one dimensional spectra consists of a weighted sum of the pixels +within the apertures at each point along the dispersion axis. The +weighting options provide the simple sum of the pixel values and a +weighting by the expected uncertainty of each pixel. Two dimensional +extractions interpolate the spectra in the spatial axis to produce +image strips with the position of the spectra exactly aligned with one +of the image dimensions. The extractions also include optional +background subtraction, modeling, and bad pixel detection and replacement. +The tasks are flexible in their ability to define and edit apertures, +operate on lists of images, use apertures defined for reference +images, and operate both very interactively or noninteractively. +The extraction tasks are efficient and require only one pass through +the data. This paper describes the tasks, the algorithms, the data +structures, as well as some examples and possible future developments. +.AE +.NH +Introduction +.PP +The IRAF \fBapextract\fR package provides tools for the extraction of +one and two dimensional aperture spectra from two dimensional format +images such as those produced by echelle, long slit, multi-fiber, and +multi-slit spectrographs. This type of data is becoming increasingly +popular because of the efficiency of data collection and recent +technological improvements such as fibers and digital detectors. +The trend is also to greater and greater numbers of spectra per +image. Extraction is one of the fundamental operations performed +on these types of two dimensional spectral images, so a great deal of effort +has gone into the design and development of this package. +.PP +The tasks are flexible and have many options. To make the best use of +them it is important to understand how they work. This paper provides +a general description of the tasks, the algorithms, the data structures, +as well as some examples of usage. Specific descriptions of parameters +and usage may be found in the IRAF help pages for the tasks included +as appendices to this paper. The image reduction "cookbooks" also +provide complete examples of usage for specific instruments or types +of instruments. +.PP +The tasks in the \fBapextract\fR pacakge are summarized below. + +.ce +The \fBApextract\fR Package +.TS +center; +n. +apdefault \&- Set the default aperture parameters +apedit \&- Edit apertures interactively +apfind \&- Automatically find spectra and define apertures +apio \&- Set the I/O parameters for the APEXTRACT tasks +apnormalize \&- Normalize 2D apertures by 1D functions +apstrip \&- Extract two dimensional aperture strips +apsum \&- Extract one dimensional aperture sums +aptrace \&- Trace positions of spectra +.TE + +The tasks are highly integrated so that one task may call another tasks +or use its parameters. Thus, these tasks reflect the logical organization +of the package rather than a set of disparate tools. One reason for +this organization is group the parameters by function into easy to manage +\fIparameter sets (psets)\fR. The tasks \fBapdefault\fR and \fBapio\fR +are just psets for specifying the default aperture parameters and the +I/O parameters of the package; in other words, they do nothing but +provide a grouping of parameters. Executing these tasks is a shorthand +for the command "eparam apdefault" or "eparam apio". The other tasks +provide both a logical grouping of parameters and function. For +example the task \fBaptrace\fR traces the positions of the spectra +in the images and has the parameters related to tracing. The task +\fBapsum\fR, however, may trace the spectra as part of the overall +extraction process and it uses the functionality and parameters of +the \fBaptrace\fR task without requiring all the tracing parameters +be included as part of its parameter set. As we examine each task +in detail it will become more apparent how this integration of function +and parameters works. +.PP +The \fBapextract\fR package identifies the image axes with the spatial +and dispersion axes. Thus, during extraction pixels of constant +wavelength are those along a line or column. In this paper the terms +\fIslit\fR or \fIspatial\fR axis and \fIdispersion\fR or \fIwavelength\fR +axis are used to refer to the image axes corresponding to the spatial +and dispersion axes. Often a small degree of misalignment between the +image axes and the true dispersion and spatial axes is not important. +The main effect of misalignment is a broadening of the spectral +features due to the difference in wavelength on opposite sides of the +extraction aperture. If the misalignment is significant, however, the +image may be rotated with the task \fBrotate\fR in the \fBimages\fR +package or remapped with the \fBlongslit\fR package tasks for +coordinate rectification. +.PP +It does not matter which image axis is the dispersion axis since the +tasks work equally well in either orientation. However, the dispersion +axis must be defined, with the \fBtwodspec\fR task \fBsetdisp\fR, +before these tasks may be used. This task is a simple script which +adds the parameter DISPAXIS to the image headers. The \fBapextract\fR +tasks, like the \fBlongslit\fR tasks, look in the header to determine +the dispersion axis. +.NH +Apertures +.PP +Apertures are the basic data structures used in the package; hence the +package name. An aperture defines a region of the two dimensional image +to be extracted. The aperture definitions are stored in a database. +An aperture consists of the following components. + +.IP ID +.br +An integer identification number. The identification number must be +unique. It is used as the default extension during extraction of +the spectra. Typically the IDs are consecutive positive integers +ordered by increasing or decreasing slit position. +.IP BEAM +.br +An integer beam number. The beam number need not be +unique; i.e. several apertures may have the same beam number. +The beam number will be recorded in the image header of the +the extracted spectrum. By default the beam number is the same as +the ID. +.IP APAXIS +.IP CENTER[2] +.br +The center of the aperture along the slit and dispersion axes in the two +dimensional image. +.IP LOWER[2] +.br +The lower limits of the aperture, relative to the aperture center, +along the slit and dispersion axes. The lower limits need not be less +than the center. +.IP UPPER[2] +.br +The upper limits of the aperture, relative to the aperture center, +along the slit and dispersion axes. The upper limits need not be greater +than the center. +.IP CURVE +.br +An offset to be added to the center position for the \fIslit\fR axis which is +a function of the wavelength. The function is one of the standard IRAF +types; a legendre polynomial, a chebyshev polynomial, a linear spline, +or a cubic spline. +.IP background +.br +Parameters for background subtraction based on the interactive +curve fitting (\fBicfit\fR) tools. + +.PP +The aperture center is the only absolute coordinate (relative to the +image or image section). The other aperture parameters and the +background fitting regions are defined relative to the center. Thus, +an aperture may be repositioned easily by changing the center +coordinates. Also a constant aperture size, shape (curve), and +background regions may be maintained for many apertures. The center +and aperture limits, in image coordinates, along the slit axis are +given by: + +.EQ I + ~roman center ( lambda )~mark = roman cslit + roman curve ( lambda ) +.EN +.EQ I +roman lower ( lambda )~lineup = roman center ( lambda ) + roman lslit +.EN +.EQ I +roman upper ( lambda )~lineup = roman center ( lambda ) + roman uslit +.EN + +where $lambda$ is the wavelength coordinate. Note that both the lower and +upper constants are added to the center defined by the aperture center and +the offset curve. The aperture limits along the dispersion axis are +constant since there is no offset curve: + +.EQ I +roman center (s)~lineup = roman cdisp +.EN +.EQ I +roman lower (s)~lineup = roman center (s) + roman ldisp +.EN +.EQ I +roman upper (s)~lineup = roman center (s) + roman udisp +.EN + +.PP +Apertures for a particular image may be defined in several ways. +These methods are arranged in a hierarchy. + +.IP (1) +The database is first searched for previously defined apertures. +.IP (2) +If no apertures are found and a reference image is specified then the +database is searched for apertures defined for the reference image. +.IP (3) +The user may then edit the apertures interactively with graphics +commands if the \fIapedit\fR parameter is set. This includes creating +new apertures and deleting or modifying existing apertures. This +interactive editing procedure may be entered from any of the \fBapextract\fR +tasks. +.IP (4) +For the tasks \fBtrace\fR, \fBsumextract\fR, and \fBstripextract\fR +if no apertures are defined at this point a default aperture +is created consisting of the entire image with center at the center of +the image. Note that if an image section is used then the aperture +spans the image section only. +.IP (5) +Any apertures created, modified, or adopted from a reference image are recorded +in the database for the image. + +.PP +There are several important points to appreciate in the above logic. +First, any of the tasks may be used without prior use of the others. +For example one may use extract with the \fIapedit\fR switch set and +define the apertures to be extracted (except for tracing). +Alternatively the apertures may be defined with \fBapedit\fR +interactively and then traced and extracted noninteractively. Second, +image sections may be used to define apertures (step 4). For example +a list of image sections (such as are used in multislit spectra) may be +extracted directly and noninteractively. Third, multiple images may +use a reference image to define the same apertures. There are several +more options which are illustrated in the examples section. +.PP +Another subtlety is the way in which reference images may be +specified. The tasks in the package all accept list of images +(including image sections). Reference images may also be given as a +list of images. The lists, however, need not be of the same length. +The reference images in the reference image list are paired in order +with the input images. If the reference list ends before the image +list then the last reference image is used for the remaining images. +The most common situations are when there is no reference image, when +only one reference image is given for a set of input images, and when a +matching list of reference images is given. In the second case the +reference image refers to all the input images while in the last case +each input image has a reference image. +.PP +There is a trick which may be played with the reference images. If a list +of input images is given and the reference image is the same as the first +input image then only the first image need be done interactively. +This is because after the apertures for the first image have been defined +they are recorded in the database. Then when the database is searched +for apertures for the second image, the apertures of the reference image +will be available. +.NH +.PP +\fBApedit\fR is a generally interactive task which graphs a line of +an image along the slit axis and allows the user to define and edit +apertures with the graphics cursor. The defined apertures are recorded +in a database. The task \fBtrace\fR traces the positions of the +spectrum profiles from one wavelength to other wavelengths in the image +and fits a smooth curve to the positions. This allows apertures +to follow shifts in the spectrum along the slit axis. The tasks +\fBsumextract\fR and \fBstripextract\fR perform the actual aperture +extraction to one and two dimensional spectra. They have options for +performing background subtraction, detecting and replacing bad pixels, +modeling the spectrum profile, and weighting the pixels in the aperture +when summing across the dispersion. +.NH +Tracing +.PP +The spectra to be extracted are not always aligned exactly with the +image columns or lines (the extraction axes). +For consistent extraction it is important that the same +part of the spectrum profile be extracted at each wavelength point. +Thus, the extraction apertures allow for shifts along the spatial axis +at each dispersion point. The shifts are defined by a curve which is a +function of the wavelength. The curve is determined by tracing the +positions of the spectrum profile at a number of wavelengths and +fitting a function to these positions. +.PP +The task \fBtrace\fR performs the tracing and curve fitting and records +the curve in the database. The starting point along the +dispersion axis (a line or column) for the tracing is specified by the +user. The position of the profile is then determined using the +\fBcenter1d\fR algorithm described elsewhere (see the help page for +\fBcenter1d\fR or the paper \fIThe Long Slit Reduction Package\fR). +The user specifies a step along the dispersion axis. At each step the +positions of the profiles are redetermined using the preceding +position as the initial guess. In order to enhance and trace weak +spectra the user may specify a number of neighboring profiles to be +summed before determining the profile positions. +.PP +Once the +positions have been traced from the starting point to the ends of the +aperture, or until the positions become indeterminate, a curve of a +specified type and order is fit to the positions as a function of +wavelength. The function fitting is performed with the \fBicfit\fR +tools (see the IRAF help page). The curve fitting may be performed +interactively or noninteractively. Note that when the curve is fit +interactively the actually positions measured are graphed. However, the +curve is stored in the aperture definition as an offset relative to the +aperture center. +.PP +The tracing requires that the spectrum profile have a shape from which +\fBcenter1d\fR can determine a position. This pretty much means +gaussian type profiles. To extract a part of a long slit spectrum +which does not have such a profile the user must trace a profile from +another part of the image or a different image and then shift the +center of the aperture without changing the shape. For example the +center of a extended galaxy spectrum can be traced and the aperture +shifted to other parts of the galaxy. +.NH +Extraction +.PP +There are two types of extraction; strip extraction and sum +extraction. Strip extraction produces two dimensional images with +pixels corresponding to the center of an aperture aligned along the +lines or columns. Sum extraction consists of the weighted sum of the +pixels within an aperture along the image axis nearest the spatial axis +at each point along the dispersion direction. It is important to +understand that the extraction is along image lines or columns while +the actual dispersion/spatial coordinates may not be aligned exactly +with the image axes. If this misalignment is important then for simple +rotations the task \fBrotate\fR in the \fBimages\fR package may be used +while for more complex coordinate rectifications the tasks in the +\fBlongslit\fR package may be used. +.NH 2 +Sum Extraction +.PP +Denote the image axis nearest the spatial axis by the index $s$ and +the other image axis corresponding to the dispersion axis by $lambda$. +The extraction is defined by the equation + +.EQ I (1) +f sub lambda~=~sum from s (W sub sl (I sub sl - B sub sl ) / P sub sl ) / +sum from s W sub sl +.EN + +where the sums are over all pixels along the spatial axis within some +aperture. The $W$ are weights, the $I$ are pixel intensities, +the $B$ are background intensities, and the $P$ are a normalized +profile model. +.PP +There are many possible choices for the extraction weights. The extraction +task currently provides two: + +.EQ I (2a) +W sub sl~mark =~P sub sl +.EN +.EQ I (2b) +W sub sl~lineup =~P sub sl sup 2 / V sub sl +.EN + +where $V sub sl$ is the variance of the pixel intensities given by the +model + +.EQ I + V sub sl~=~v sub 0 + v sub 1~max (0,~I sub sl )~~~~if v sub 0~>~0 +.EN +.EQ I + V sub sl~=~v sub 1~max (1,~I sub sl )~~~~~~~~~if v sub 0~=~0 +.EN + +Substituting these weights in equation (1) yields the extraction equations + +.EQ I (3a) +f sub lambda~mark =~sum from s (I sub sl - B sub sl ) +.EN +.EQ I (3b) +f sub lambda~lineup =~sum from s (P sub sl (I sub sl - B sub sl ) / V sub sl ) / +sum from s (P sub sl sup 2 / V sub sl ) +.EN + +.PP +The first type of weighting (2a), called \fIprofile\fR weighting, weights +by the profile. Since the weights cancel this gives the simple extraction (3a) +consisting of the direct summation of the pixels within the aperture. +It has the virtue of being simple and computationally fast (since the +profile model does not have to be determined). +.PP +The second type of weighting (2b), called \fIvariance\fR weighting, +uses a model for the variance of the pixel intensities. +The model is based on Poisson statistics for a linear quantum detector. +The first term is commanly call the \fIreadout\fR noise and the second term +is the Poisson noise. The actual value of $v sub 1$ is the reciprical of +the number of photons per digital intensity unit (ADU). A simple variant of +this type of weighting is to let $v sub 1$ equal zero. Since the actual +scale of the variance cancels we can then set $v sub 0$ to unity to obtain + +.EQ I (4) +f sub lambda~=~sum from s (P sub sl (I sub sl - B sub sl )) / +sum from s P sub sl sup 2 . +.EN + +The interpretation of this extraction is that the variance of the intensities +is constant. It gives greater weight to the stronger parts of the spectrum +profile than does the profile weighting (3a) since the weights are +$P sub sl sup 2$. Equation (4) has the virtue that one need not know the +readout noise or the ADU to photon number conversion. +.NH 3 +Optimal Extraction +.PP +Variance weighted extraction is sometimes called optimal extraction because +it is optimal in a statistical sense. Specifically, +the relative contribution of a pixel to the sum is related to the uncertainty +of its intensity. The uncertainty is measured by the expected variance of +a pixel with that intensity. The degree of optimality depends on how well +the relative variances of the pixels are known. +.PP +A discussion of the concepts behind optimal extraction is given in the paper +\fIAn Optimal Extraction Algorithm for CCD Spectroscopy\fR by Keith Horne +(\fBPASP\fR, June 1986). The weighting described in Horne's paper is the +same as the variance weighting described in this paper. The differences +in the algorithms are primarily in how the model profiles $P sub sl$ are +determined. +.NH 3 +Profile Determination +.PP +The profiles of the spectra along the spatial axis are determined when +either the detection and replacement of bad pixels or variance +weighting are specified. The requirements on the profiles are that +they have the same shape as the image profiles at a each dispersion +point and that they be as noise free and uncontaminated as possible. +The algorithm used to create these profiles is to average a specified +number of consecutive background subtracted image profiles immediately +preceding the wavelength to which a profile refers. When there are an +insufficient number of image profiles preceding the wavelength being +extracted then the following image profiles are also used to make up +the desired number. The image profiles are interpolated to a common +center before averaging using the curve given in the aperture +definition. The averaging reduces the noise in the image data while +the centering eliminates shifts in the spectrum as a function of +wavelength which would broaden the profile relative to the profile of a +single image line or column. It is assumed that the spectrum profile +changes slowly with wavelength so that by using profiles near a given +wavelength the average profile shape will correctly reflect the profile +of the spectrum at that wavelength. +.PP +The average profiles are determined in parallel with the extraction, +which proceeds sequentially through the image. Initially the first set +of spectrum profiles is read from the image and interpolated to a common +center. The profiles are averaged excluding the first profile to be +extracted; the image profiles in the average never include the image +profile to be extracted. Subsequently the average profile is updated +by adding the last extracted image profile and subtracting the image +profile which no longer belongs in the average. This allows each image +profile to be accessed and interpolated only once and makes the +averaging computationally efficient. This scheme also allows excluding +bad pixels from the average profile. The average profile is used to +locate and replace bad pixels in the image profile being extracted as +discussed in the following sections. Then when this profile is added +into the average for the next image profile the detected bad pixels are +no longer in the profile. +.PP +In summary this algorithm for determining the spectrum profile +has the following advantages: + +.IP (1) +No model dependent smoothing is done. +.IP (2) +There is no assumption required about the shape of the profile. +The only requirement is that the profile shape change slowly. +.IP (3) +Only one pass through the image is required and each image profile +is accessed only once. +.IP (4) +The buffered moving average is very efficient computationally. +.IP (5) +Bad pixels are detected and removed from the profile average as the +extraction proceeds. + +.NH 3 +Detection and Elimination of Bad Pixels +.PP +One of the important features of the aperture extraction package is the +detection and elimination of bad pixels. The average profile described +in the previous section is used to find pixels which deviate from this +profile. The algorithm is straightforward. A model spectrum of the +image profile is obtained by scaling the normalized profile to the +image profile. The scale factor is determined using chi squared fitting: + +.EQ I (6) +M sub sl~=~P sub sl~left { sum from s ((I sub sl - B sub sl ) P sub sl / +V sub sl)~/~ sum from s (P sub sl sup 2 / V sub sl ) right } . +.EN + +The RMS of this fit is determined and pixels deviating by more than a +user specified factor times this RMS are rejected. The fit is then +repeated excluding the rejected points. These steps are repeated until +the user specified number of points have been rejected or no further deviant +points are detected. The rejected points in the image profile are then +replaced by their model values. +.PP +This algorithm is based only on the assumption that the spatial profile +of the spectrum (no matter what it is) changes slowly with wavelength. +It is very sensitive at detecting departures from the expected profile. +Its main defect is that in the first pass at the fit all of the image profile +is used. If there is a very badly deviant point and the rest of the profile +is weak then the scale factor may favor the bad pixel more than the +rest of the profile resulting in rejecting good profile points and not +the bad pixel. +.NH 3 +Relation of Optimal Extraction to Model Extraction +.PP +Equation (1) defines the extraction process in terms of a weighted sum +of the pixel intensities. However, the actual extraction operations +performed by the task \fBsumextract\fR are + +.EQ I (7a) +f sub lambda~mark =~sum from s (I sub sl - B sub sl ) +.EN +.EQ I (7b) +f sub lambda~lineup =~sum from s M sub sl +.EN + +where $M sub sl$ is the model spectrum fit to the background subtracted +image spectrum $(I sub sl - B sub sl )$ +defined in the previous section (equation 6). It is not obvious at first that +(7b) is equivalent to (3b). However, if one sums (6) and uses the fact +that the sum of the normalized profile is unity one is left with equation (3b). +.PP +Equations (6) and (7b) provide an alternate way to think about the +extracted one dimensional spectra. Sum extraction of the model spectrum +is used instead of the weighted sum for variance weighted extraction +because the model spectrum is a product of the profile determination +and the bad pixel cleaning process. It is then more convenient +and efficient to use the simple equations (7). +.NH 2 +Strip Extraction +.PP +The task \fBstripextract\fR uses one dimensional image interpolation +to shift the pixels along the spatial axes so that in the resultant +output image the center of the aperture is exactly aligned with the +image lines or columns. The cleaning of bad pixels is an option +in this extraction using the methods described above. In addition +the model spectrum described above may be extracted as a two +dimensional image. In fact, the only difference between strip extraction +and sum extraction is whether the final step of summing the pixels +in the aperture along the spatial axis is performed. +.PP +The primary use of \fBstripextract\fR is as a diagnostic tool. It +allows the user to see the background subtracted, cleaned and/or model +spectrum as an image before it is summed to a one dimensional spectrum. +In addition the two dimensional format allows use of other IRAF tools such as +smoothing operators. When appropriate +it is a much simpler method of removing detector distortions and alignment +errors than the full two dimensional mapping and image transformation +available with the \fBlongslit\fR package. +.NH +Examples +.de CS +.nf +.ft L +.. +.de CE +.fi +.ft R +.. +.PP +This section is included because the flexibility and many options of +the tasks allows a wide range of applications. The examples illustrate +the use of the task parameters for manipulating input images, output +images, and reference images, and setting apertures interactively and +noninteractively. They do not illustrate the different possibilities +in extraction or the interactive aperture definition and editing +features. These examples are meant to be relevant to actual data +reduction and analysis problems. For the purpose of these examples we +will assume the dispersion axis is along the second image axis; i.e. +DISPAXIS = 2. +.PP +The simplest problem is the extraction of an object spectrum which +is centered on column 200. To extract the spectrum with an aperture +width of 20 pixels an image section can be used. + +.CS +cl> sumextract image[190:209,*] obj1d +cl> stripextract image[190:209,*] obj2d +.CE + +To set the aperture center and limits interactively the edit option can be +used with or without the image section. This also allows fractional pixel +centering and limits. +.PP +If the object slit position changes the spectrum profile can be traced first +and then extracted. + +.CS +cl> trace image[190:209,*] +cl> sumextract image[190:209,*] obj1d +cl> stripextract image[190:209,*] obj2d +.CE + +By default the apertures are defined and/or edited interactively in +\fBtrace\fR and editing is not the default in \fBsumextract\fR or +\fBstripextract\fR. +.PP +A more typical example involves many images. In this case a list of images +is used though, of course, each image could be done separately as +in the previous examples. There are three common forms of lists, a +pattern matching template, a comma separated list, and an "@" file. +In addition the template editing metacharacter, "%", may be used +to create new output image names based on input image names. +If the object positions are different in each image then we can select +apertures with image sections or using the editing option. Some examples +are + +.CS +cl> sumextract image1[10:29,*],image2[32:51] obj1,obj2 +cl> sumextract image* e//image* edit+ +cl> sumextract image* image%%ex%* edit+ +cl> sumextract @images @images edit+ +.CE + +The "@" files can be created from the other two types of lists using the +\fBsections\fR task in the \fBimages\fR package. An important feature +of the image templates is the use of the concatenation operator. Note, +however, this a feature of image templates and not file templates. +Also the output root name may be the same as the input +name because an extension is added provided there are no image +sections in the input images. +.PP +If the object positions are the same then the apertures can be defined once +and the remaining objects can be extracted using a reference image. + +.CS +cl> apedit image1 +cl> sumextract image* image* ref=image1 +.CE + +Rather than using \fBapedit\fR one can use \fBsumextract\fR alone with +the edit switch set. The command is + +.CS +cl> sumextract image* image* ref=image1 edit+ +.CE + +The task queries whether to edit the apertures for each image. +For the first image respond with "yes" and set the apertures interactively. +For the second task respond with "NO". Since the aperture for "image1" +was recorded when the first image was extracted it then acts as the reference +for the remaining images. The emphatic response "NO" turns off the edit switch +for all the other images. One difference between this example and the +previous one is that the task cannot be run as a background batch task. +.PP +The extension to using traced apertures in the preceding examples is +very similar. + +.CS +cl> apedit image1 +cl> trace image* ref=image1 edit- +cl> sumextract image* image* +cl> stripextract image* image* +.CE + +.PP +Another common type of data has multiple spectra on each image. Some examples +are echelle and multislit spectra. Echelle extractions usually are done +interactively with tracing. Thus, the commands are + +.CS +cl> trace ech* +cl> sumextract ech* ech* +.CE + +For multislit spectra the slitlets are usually referenced by creating +an "@" file containing the image sections. The usage for extraction +is then + +.CS +cl> sumextract @slits @slitsout +.CE + +.PP +The aperture definitions can be transfered from a reference image to +other images using \fBapedit\fR. There is no particular reason to +do this except that reference images would not be needed in +\fBtrace\fR, \fBsumextract\fR or \fBstripextract\fR. The transfer +is accomplished with the following command + +.CS +cl> apedit image1 +cl> apedit image* ref=image1 edit- +.CE + +The above can also be combined into one step by editing the first image +and then responding with "NO" to the second image query. +.NH +Future Developments +.PP +The IRAF extraction package \fBapextract\fR is going to continue to +evolve because 1) the extraction of one and two dimensional spectra +from two dimensional images is an important part of reducing echelle, +longslit, multislit, and multiaperture spectra, 2) the final strategy +for handling multislit and multiaperture spectra produced by aperture +masks or fiber optic mapping has not yet been determined, and 3) the +extraction package and the algorithms have not received sufficient user +testing and evaluation. Changes may include some of the following. + +.IP (1) +Determine the actual variance from the data rather than using the Poisson +CCD model. +.IP (2) +Another task, possibly called \fBapfind\fR, is needed to automatically find +profile positions in multiaperture, multislit, and echelle spectra. +.IP (3) +The bad pixel detection and removal algorithm does not handle well the case +of a very strong cosmic ray event on top of a very weak spectrum profile. +A heuristic method to make the first fitting pass of the average +profile to the image data less prone to errors due to strong cosmic rays +is needed. +.IP (4) +The aperture definition structure is general enough to allow the aperture +limits along the dispersion dimension to be variable. Eventually aperture +definition and editing will be available using an image display. Then +both graphics and image display editing switches will be available. +An image display interface will make extraction of objective prism +spectra more convenient than it is now. +.IP (5) +Other types of extraction weighting may be added. +.IP (6) +Allow the extraction to be locally perpendicular to the traced curve. diff --git a/noao/twodspec/apextract/doc/old/apextract1.ms b/noao/twodspec/apextract/doc/old/apextract1.ms new file mode 100644 index 00000000..b586daad --- /dev/null +++ b/noao/twodspec/apextract/doc/old/apextract1.ms @@ -0,0 +1,811 @@ +.EQ +delim $$ +define sl '{s lambda}' +.EN +.RP +.TL +The IRAF APEXTRACT Package +.AU +Francisco Valdes +.AI +IRAF Group - Central Computer Services +.K2 +P.O. Box 26732, Tucson, Arizona 85726 +.AB +The IRAF \fBapextract\fR package provides tools for the extraction of +one and two dimensional spectra from two dimensional images +such as echelle, long slit, multifiber, and multislit spectra. +Apertures of fixed spatial width define the regions of +the two dimensional images to be extracted at each point along the +dispersion axis. Apertures may follow changes in the positions of +the spectra as a function of position along the dispersion axis. +The spatial and dispersion axes may be oriented along either image axis. +Extraction to one dimensional spectra consists of a weighted sum of the pixels +within the apertures at each point along the dispersion axis. The +weighting options provide the simple sum of the pixel values and a +weighting by the expected uncertainty of each pixel. Two dimensional +extractions interpolate the spectra in the spatial axis to produce +image strips with the position of the spectra exactly aligned with one +of the image dimensions. The extractions also include optional +background subtraction, modeling, and bad pixel detection and replacement. +The tasks are flexible in their ability to define and edit apertures, +operate on lists of images, use apertures defined for reference +images, and operate both very interactively or noninteractively. +The extraction tasks are efficient and require only one pass through +the data. This paper describes the package organization, the tasks, +the algorithms, and the data structures. +.AE +.NH +Introduction +.PP +The IRAF \fBapextract\fR package provides tools for the extraction of +one and two dimensional aperture spectra from two dimensional format +images such as those produced by echelle, long slit, multifiber, and +multislit spectrographs. This type of data is becoming increasingly +common because of the efficiency of data collection and technological +improvements in spectrographs and detectors. The trend is to greater +and greater numbers of spectra per image. Extraction is one of the +fundamental operations performed on these types of two dimensional +spectral images, so a great deal of effort has gone into the design and +development of this package and to making it easy to use. +.PP +The tasks are flexible and have many options. To make the best use of +them it is important to understand how they work. This paper provides +a general description of the package organization, the tasks, the algorithms, +and the data structures. Specific descriptions of parameters +and usage may be found in the IRAF help pages for the tasks which +are included as appendices to this paper. The image reduction "cookbooks" +also provide examples of usage for specific instruments or types +of instruments. +.PP +Extraction of spectra consists of three logical steps. First, locating +the spectra in the two dimensional image. This includes defining the +dispersion direction, the positions of the spectra at some point +along the dispersion direction, the spatial extent or aperture to be +used for extraction, and possible information about where the background +for each spectrum is to be determined. This information is maintained +in the package as structures called \fIapertures\fR. The second step is +to measure the positions of the spectra at other points along the dispersion. +This process is called tracing. Tracing is optional if the spectra +are exactly aligned with the dispersion direction. The final step is +to extract the spectra into one or two dimensional images. +.PP +The \fBapextract\fR package identifies the image axes with the spatial +and dispersion axes. Thus, during extraction, pixels of constant +wavelength are assumed to be along a line or column. In this paper the +terms \fIslit\fR or \fIspatial\fR axis and \fIdispersion\fR or +\fIwavelength\fR axis are used to refer to the image axes corresponding +to the spatial and dispersion axes. To simplify the presentation a +cut across the dispersion axis will be called a line even though it +could also be a column. +.PP +Often a small degree of +misalignment between the image axes and the true dispersion and spatial +axes is not important. The main effect of misalignment is a broadening +of the spectral features due to the difference in wavelength on +opposite sides of the extraction aperture. If the misalignment is +significant, however, the image may be rotated with the task +\fBrotate\fR in the \fBimages\fR package or remapped with the +\fBlongslit\fR package tasks for coordinate rectification. +.PP +It does not matter which image axis is the dispersion axis since the +tasks work equally well in either orientation. However, the dispersion +axis must be defined, with the \fBtwodspec\fR task \fBsetdisp\fR, +before these tasks may be used. This task is a simple script which +adds the parameter DISPAXIS to the image headers. The \fBapextract\fR +tasks, like the \fBlongslit\fR tasks, look in the header to determine +the dispersion axis. +.NH +The APEXTRACT Package +.PP +In this section the organization of the \fBapextract\fR package and the +functions and parameters of the tasks are briefly described. More detailed +descriptions are given in the help pages for the tasks. The tasks in the +package are: + +.ce +.ft B +The APEXTRACT Tasks + +.ft L +.nf + apdefault - Set the default aperture parameters + apedit - Edit apertures interactively + apfind - Automatically find spectra and define apertures + apio - Set the I/O parameters for the APEXTRACT tasks + apnormalize - Normalize 2D apertures by 1D functions + apstrip - Extract two dimensional aperture strips + apsum - Extract one dimensional aperture sums + aptrace - Trace positions of spectra +.fi +.ft R + +.PP +The tasks are highly integrated so that each task includes some or all of +the functions and parameters of the other tasks. Thus, these tasks +reflect the logical organization of the extraction process rather than +a set of disparate tools. One reason for this organization is to group +the parameters by function into easy to manage \fIparameter sets +(psets)\fR. The tasks \fBapdefault\fR and \fBapio\fR are just psets +for specifying the default aperture parameters and the I/O parameters +of the package; in other words, they do nothing but provide a grouping +of parameters. Executing these tasks is a shorthand for the command +"eparam apdefault" or "eparam apio". +.PP +The input/output parameters in \fBapio\fR specify the aperture database, +an optional log file for brief, time stamped log information, an optional +metacode plot file for saving plots of the apertures, the traces, and the +quick look extracted spectra, and the graphics input and output devices +(almost always the user's terminal). One point about the plot file is +that the plots are recorded even if the user chooses not to view these +graphs as the task is run interactively or noninteractively. This allows +reviewing the traces and spectra with a tool like \fBgkimosaic\fR. +.PP +The default aperture parameters specify the aperture limits (basically +the width of the aperture and position relative to the center of the +spectrum) and the background fitting parameters. The background +parameters are the standard parameters used by the \fBicfit\fR package +with which the user is assumed to be familiar. For more on this see +the help information for \fBicfit\fR. +.PP +The other tasks are both psets and executable tasks. There are a +number features which are common to all these tasks. First, they +follow the same steps in defining apertures for the input images. +These steps are: +.IP (1) +If a reference image is specified then the database is searched for +apertures previously defined for this image. +.IP (2) +If apertures are found for the reference image they may be recentered +on the spectra in the input image at a specified line. This does not +change the shape of the apertures but only adds a shift in the center +coordinate of the apertures along the spatial axis. +.IP (3) +If a reference image is not specified or if no reference apertures are found +then the database is searched for previous apertures for the input image. +.IP (4) +If there are no apertures defined either from a reference image or previous +apertures for the input image then an automatic algorithm may be used to find +a specified number of spectra (based on peak values) and assign them default +apertures. +.IP (5) +Finally, a sophisticated graphical aperture editor may be used to examine, +define, and modify apertures. +.IP (6) +When tracing, extracting, or normalizing flat field spectra, +if no apertures have been defined by the steps above then a single default +aperture, centered in the image, is defined. + +Any apertures created, modified, or adopted from a reference image +may be recorded in the database for the input image. +.PP +The operations listed above are selected by parameters common to each of the +tasks. For example the parameter \fIedit\fR selects whether to enter +the aperture editor and is present in each of the executable tasks. +On the other hand the parameters specific to the aperture editor, +while accessed by any of the tasks, reside only in the parameter set of +the task \fBapedit\fR. In this way parameters are distributed +by logical function rather than including them in each task. +.PP +In addition to the aperture editing and finding functions available in +every task, some of the tasks include functions for tracing, extracting, +or normalizing the spectra. The tasks \fBapsum\fR and \fBapstrip\fR, +which extract one and two dimensional spectra, are at the top of the +hierarchy and include all the logical functions provided by the package. +Thus, in most cases the user need only use the task \fBapsum\fR to define +apertures, trace the spectra, and extract them. +.PP +Another feature common to the tasks is their interactive and noninteractive +modes. When the parameter \fIinteractive\fR is set to \fIno\fR then the +aperture editing, interactive trace fitting, and review of the extracted +one dimensional spectra functions of the package are bypassed. Note that +this means you do not have to explicitly set the parameter \fIedit\fR, +or those for other purely interactive functions, +to \fIno\fR when extracting spectra noninteractively. In the noninteractive +mode there are also no queries. +.PP +The interactive mode includes the interactive graphical functions of +aperture editing, trace fitting, and extraction review. In addition +the user is queried at each step. For example the user will be queried +whether to edit the apertures for a particular image if the task +parameter for editing is set. The queries have four responses: \fIyes, +no, YES,\fR and \fINO\fR. The lower case responses apply only to the +particular query. The upper case responses apply to any further +queries of the same type and suppress the query from appearing again. +This is particularly useful when dealing with many images or many +apertures. For example, when fitting the traced points interactively +the user may examine the first few and then say \fINO\fR to skip the +remaining apertures using the last defined fitting parameters. Note +that if a plot file is specified the graphs showing the traced points +and the fits are recorded even if they are not viewed interactively. +.NH +Algorithms +.PP +The \fBapextract\fR package consists of a number of logical functions or, +in computerese, algorithms. These algorithms manipulate the aperture +structure data and create output data in the form of images. In +this section the various algorithms are described. In addition to the +algorithms specific to the package, there are some general algorithms +and tools used which appear in other IRAF tasks. Specifically there are the +interactive curve fitting tools called \fBicfit\fR and the one +dimensional centering algorithm called \fBcenter1d\fR. These are +mentioned below and described in detail elsewhere in the help documentation. +.NH 2 +Finding Spectra +.PP +When dealing with images containing large numbers of spectra it may be +desirable to locate the spectra and define apertures automatically. The +\fBapfind\fR algorithm provides this ability from any of the executable +tasks and from the aperture editor using the 'f' key. It takes a cut +across the dispersion axis by summing one or more image lines. +All the local maxima are identified and ranked by intensity. Starting +with the highest maxima any other peaks within a specified minimum +separation are eliminated. The weakest remaining peaks exceeding the +specified number are eliminated next. The positions of the +spectra based on peak positions are refined by centering using the +\fBcenter1d\fR algorithm. Finally identical apertures are assigned +for each spectrum found. +.PP +When the algorithm is invoked by a task, with the parameter \fIfind\fR, +there must be no previous or reference apertures in the database. +The apertures assigned to the spectra have the parameters +specified in the \fBapdefault\fR pset. When the algorithm is invoked +from the aperture editor with the 'f' key then new apertures are +added to any existing apertures up to the total number of apertures, +existing plus new, given by the \fInfind\fR parameter. If there +is a current aperture then copies of it are used to define the +apertures for the new spectra. Thus, one method for defining many +apertures is to use the editor to define one aperture, set its +limits and background parameters, and then find the remaining apertures +automatically. +.NH 2 +Centering and Recentering +.PP +When new apertures are defined (except for a special key to mark apertures +without centering) or when apertures are recentered, either with the +centering key in the editor or with the task parameter \fIrecenter\fR, +the center is determined using the \fBcenter1d\fR algorithm. +This is described in the help documentation under the name \fBcenter1d\fR. +Briefly, the data line is convolved with an asymmetric function of specified +width. The convolution integral is evaluated using image interpolation. +The sign of the convolution acts as a gradient to move from the starting +position to the final position where the convolution is zero. This algorithm +is good to about 5% of a pixel. It has two important parameters; the +width of the convolution and the error distance between the starting +and final positions. The width of the convolution determines the scale +of features to which the centering is sensitive. The error distance is +the greatest change allowed in the initial positions. If this error +distance is exceeded then the centering fails and either a new aperture +is not defined or the position of an existing aperture is not changed. +.NH 2 +The Aperture Editor +.PP +The aperture editor is a sophisticated tool for defining and modifying +apertures. It may also be used to selectively trace and extract +spectra. Thus, the aperture editor may be used alone to perform all +the functions for extracting spectra. The aperture editor uses a +graphical presentation. A line or sum of lines is displayed. The +apertures are marked above the line and identified with the aperture +number. Information about the current aperture is shown on the status +line. The cursor is used to mark new apertures, shift the center or +aperture limits, and perform a variety of functions. Because there may +be many apertures which the user wants to modify in the same way there +is a mode switch to apply commands to all the apertures. The switch is +toggled with the 'a' key and the mode is indicated on the status line. +.PP +There are also a number of colon commands. These allow resetting parameters +explicitly rather than by cursor and interacting with the aperture +database and the image data. The background fitting parameters such as +the background regions and function order are set by switching to the +interactive curve fitting package \fBicfit\fR. The line being edited is +used to set the parameters. No background is actually extracted at this +stage. The ALL mode applies to the background parameters as well. +.PP +The aperture editor has many commands. For a description of the +commands see the help information for the task \fBapedit\fR. In +summary the aperture editor is used to interactively define apertures, +both centered on spectra and at arbitrary positions, adjust the limits +and background parameters, and possibly select apertures to be traced +and extracted. These functions may be applied independently on each +aperture for maximum flexibility or applied to all apertures for ease +of use with many apertures. +.NH 2 +Tracing +.PP +The spectra to be extracted are not always aligned exactly with the +image columns or lines. For consistent +extraction it is important that the same part of the spectrum profile +be extracted at each wavelength point. Thus, the extraction apertures +allow for shifts along the spatial axis at each wavelength. The +shifts are defined by a curve which is a function of the wavelength. +The curve is determined by tracing the positions of the spectrum +profile at a number of wavelengths and fitting a function to these +positions. +.PP +The \fIaptrace\fR algorithm performs the tracing and curve fitting. +The starting point along the dispersion axis (a line or column) for +the tracing is specified by the user. The positions of the spectrum +profiles are determined using the \fBcenter1d\fR algorithm +(see the previous section on centering and the help page for \fBcenter1d\fR). +The user specifies a step along the dispersion axis. At each step the +positions of the profiles are redetermined using the preceding +positions as the initial guesses. If the positions are lost at one step +an attempt is made to recover the spectrum in the next step. If this +also fails then tracing of that spectrum in that direction is finished. +In order to enhance and trace weak spectra the user may specify a number +of neighboring profiles to be summed before determining the profile positions. +In addition to the other centering parameters, there is also a +\fIthreshold\fR parameter to define a minimum contrast between the spectrum +and the background. +.PP +Once the positions have been traced from the starting point to the ends of the +aperture, or until the positions become indeterminate, a curve of a +specified type and order is fit to the positions as a function of +wavelength. The function fitting is performed with the \fBicfit\fR +tools (see the help documentation for \fBicfit\fR). The curve fitting +may be performed interactively or noninteractively. Note that when the +curve is fit interactively the actual positions measured are graphed. +However, the curve is stored in the aperture definition as an offset +relative to the aperture center. +.PP +The tracing requires that the spectrum profile be continuous and have +some kind of maxima. This means that arc calibration spectra or +arbitrary regions of an extended object in a long slit spectrum cannot +be traced. Flat topped spectra such as quartz lamp images taken through +slits can be measured provided the width of the centering function is +somewhat wider than the profile (to avoid centering on little peaks +within the slit). For images which cannot be traced, reference apertures +from images that can be traced are used. This is how apertures for +arc spectra are defined and extracted. For sky apertures or the +wings of extended objects the reference apertures can be shifted +by the aperture editor without altering the shape of the aperture. +.NH 2 +Sum Extraction +.PP +Sum extraction consists of the weighted sum of the pixels along the spatial axis +within the aperture limits at each point along the dispersion axis. +A background at each point along the dispersion may be determined by fitting a +function to data in the vicinity of the spectrum and subtracting the +function values estimated at each point within the aperture. The estimated +background may be output as a one dimensional spectrum. Other options +include the detection and replacement of deviant points such as due to +cosmic rays. +.PP +Denote the image axis nearest the spatial axis by the index $s$ and +the other image axis corresponding to the dispersion axis by $lambda$. +The weighted extraction is defined by the equation + +.EQ I (1) +f sub lambda~=~sum from s (W sub sl (I sub sl - B sub sl ) / P sub sl ) / +sum from s W sub sl +.EN + +where the sums are over all pixels along the spatial axis within some +aperture. The $W$ are weights, the $I$ are pixel intensities, +the $B$ are background intensities, and the $P$ are a normalized +profile model. +.PP +There are many possible choices for the extraction weights. The extraction +task \fBapsum\fR currently provides two: + +.EQ I (2a) +W sub sl~mark =~P sub sl +.EN +.EQ I (2b) +W sub sl~lineup =~P sub sl sup 2 / V sub sl +.EN + +where $V sub sl$ is the variance of the pixel intensities given by the +model + +.EQ I + V sub sl~=~v sub 0 + v sub 1~max (0,~I sub sl )~~~~if v sub 0~>~0 +.EN +.EQ I + V sub sl~=~v sub 1~max (1,~I sub sl )~~~~~~~~~if v sub 0~=~0 +.EN + +Substituting these weights in equation (1) yields the extraction equations + +.EQ I (3a) +f sub lambda~mark =~sum from s (I sub sl - B sub sl ) +.EN +.EQ I (3b) +f sub lambda~lineup =~sum from s (P sub sl (I sub sl - B sub sl ) / V sub sl ) / +sum from s (P sub sl sup 2 / V sub sl ) +.EN + +.PP +The first type of weighting (2a), called \fIprofile\fR weighting, weights +by the profile. Since the weights cancel this gives the simple extraction (3a) +consisting of the direct summation of the pixels within the aperture. +It has the virtue of being simple and computationally fast (since the +profile model does not have to be determined). +.PP +The second type of weighting (2b), called \fIvariance\fR weighting, +uses a model for the variance of the pixel intensities. +The model is based on Poisson statistics for a linear quantum detector. +The first term is commonly call the \fIreadout\fR noise and the second term +is the Poisson noise. The actual value of $v sub 1$ is the reciprocal of +the number of photons per digital intensity unit (ADU). A simple variant of +this type of weighting is to let $v sub 1$ equal zero. Since the actual +scale of the variance cancels we can then set $v sub 0$ to unity to obtain + +.EQ I (4) +f sub lambda~=~sum from s (P sub sl (I sub sl - B sub sl )) / +sum from s P sub sl sup 2 . +.EN + +The interpretation of this extraction is that the variance of the intensities +is constant. It gives greater weight to the stronger parts of the spectrum +profile than does the profile weighting (3a) since the weights are +$P sub sl sup 2$. Equation (4) has the virtue that one need not know the +readout noise or the ADU to photon number conversion. +.NH 3 +Optimal Extraction +.PP +Variance weighted extraction is sometimes called optimal extraction because +it is optimal in a statistical sense. Specifically, +the relative contribution of a pixel to the sum is related to the uncertainty +of its intensity. The uncertainty is measured by the expected variance of +a pixel with that intensity. The degree of optimality depends on how well +the relative variances of the pixels are known. +.PP +A discussion of the concepts behind optimal extraction is given in the paper +\fIAn Optimal Extraction Algorithm for CCD Spectroscopy\fR by Keith Horne +(\fBPASP\fR, June 1986). The weighting described in Horne's paper is the +same as the variance weighting described in this paper. The differences +in the algorithms are primarily in how the model profiles $P sub sl$ are +determined. +.NH 3 +Profile Determination +.PP +The profiles of the spectra along the spatial axis are determined when +either the detection and replacement of bad pixels or variance +weighting are specified. The requirements on the profiles are that +they have the same shape as the image profiles at a each dispersion +point and that they be as noise free and uncontaminated as possible. +The algorithm used to create these profiles is to average a specified +number of consecutive background subtracted image profiles immediately +preceding the wavelength to which a profile refers. When there are an +insufficient number of image profiles preceding the wavelength being +extracted then the following image profiles are also used to make up +the desired number. The image profiles are interpolated to a common +center before averaging using the curve given in the aperture +definition. The averaging reduces the noise in the image data while +the centering eliminates shifts in the spectrum as a function of +wavelength which would broaden the profile relative to the profile of a +single image line or column. It is assumed that the spectrum profile +changes slowly with wavelength so that by using profiles near a given +wavelength the average profile shape will correctly reflect the profile +of the spectrum at that wavelength. +.PP +The average profiles are determined in parallel with the extraction, +which proceeds sequentially through the image. Initially the first set +of spectrum profiles is read from the image and interpolated to a common +center. The profiles are averaged excluding the first profile to be +extracted; the image profiles in the average never include the image +profile to be extracted. Subsequently the average profile is updated +by adding the last extracted image profile and subtracting the image +profile which no longer belongs in the average. This allows each image +profile to be accessed and interpolated only once and makes the +averaging computationally efficient. This scheme also allows excluding +bad pixels from the average profile. The average profile is used to +locate and replace bad pixels in the image profile being extracted as +discussed in the following sections. Then when this profile is added +into the average for the next image profile the detected bad pixels are +no longer in the profile. +.PP +In summary this algorithm for determining the spectrum profile +has the following advantages: + +.IP (1) +No model dependent smoothing is done. +.IP (2) +There is no assumption required about the shape of the profile. +The only requirement is that the profile shape change slowly. +.IP (3) +Only one pass through the image is required and each image profile +is accessed only once. +.IP (4) +The buffered moving average is very efficient computationally. +.IP (5) +Bad pixels are detected and removed from the profile average as the +extraction proceeds. + +.NH 3 +Detection and Elimination of Bad Pixels +.PP +One of the important features of the aperture extraction package is the +detection and elimination of bad pixels. The average profile described +in the previous section is used to find pixels which deviate from this +profile. The algorithm is straightforward. A model spectrum of the +image profile is obtained by scaling the normalized profile to the +image profile. The scale factor is determined using chi-squared fitting: + +.EQ I (6) +M sub sl~=~P sub sl~left { sum from s ((I sub sl - B sub sl ) P sub sl / +V sub sl )~/~ sum from s (P sub sl sup 2 / V sub sl ) right } . +.EN + +The RMS of this fit is determined and pixels deviating by more than a +user specified factor times this RMS are rejected. The fit is then +repeated excluding the rejected points. These steps are repeated until +the user specified number of points have been rejected or no further deviant +points are detected. The rejected points in the image profile are then +replaced by their model values. +.PP +This algorithm is based only on the assumption that the spatial profile +of the spectrum (no matter what it is) changes slowly with wavelength. +It is very sensitive at detecting departures from the expected +profile. It has two problems currently. Because the input line is +first interpolated to the same center as the profile, single bad pixels +are generally broadened to two bad pixels, making it harder to find the +bad data. Also, in the first pass at the fit all of the image profile +is used so if there is a very badly deviant point and the rest of the +profile is weak then the scale factor may favor the bad pixel more than +the rest of the profile. This may result in rejecting good profile +points and not the bad pixel. +.NH 3 +Relation of Optimal Extraction to Model Extraction +.PP +Equation (1) defines the extraction process in terms of a weighted sum +of the pixel intensities. However, the actual extraction operations +performed by the task \fBapsum\fR are + +.EQ I (7a) +f sub lambda~mark =~sum from s (I sub sl - B sub sl ) +.EN +.EQ I (7b) +f sub lambda~lineup =~sum from s M sub sl +.EN + +where $M sub sl$ is the model spectrum fit to the background subtracted +image spectrum $(I sub sl - B sub sl )$ +defined in the previous section (equation 6). It is not obvious at first that +(7b) is equivalent to (3b). However, if one sums (6) and uses the fact +that the sum of the normalized profile is unity one is left with equation (3b). +.PP +Equations (6) and (7b) provide an alternate way to think about the +extracted one dimensional spectra. Sum extraction of the model spectrum +is used instead of the weighted sum for variance weighted extraction +because the model spectrum is a product of the profile determination +and the bad pixel cleaning process. It is then more convenient +and efficient to use the simple equations (7). +.NH 2 +Strip Extraction +.PP +The task \fBapstrip\fR uses one dimensional image interpolation +to shift the pixels along the spatial axis so that in the resultant +output image the center of the aperture is exactly aligned with the +image lines or columns. The cleaning of bad pixels is an option +in this extraction using the methods described above. In addition +the model spectrum, described above, may be extracted as a two +dimensional image. In fact, the only difference between strip extraction +and sum extraction is whether the final step of summing the pixels +in the aperture along the spatial axis is performed. +.PP +The primary use of \fBapstrip\fR is as a diagnostic tool. It +allows the user to see the background subtracted, cleaned, and/or model +spectrum as an image before it is summed to a one dimensional spectrum. +In addition the two dimensional format allows use of other IRAF tools such as +smoothing operators. When appropriate +it is a much simpler method of removing detector distortions and alignment +errors than the full two dimensional mapping and image transformation +available with the \fBlongslit\fR package. +.NH 2 +Aperture Normalization +.PP +The special algorithm/task \fBapnormalize\fR normalizes the two dimensional +image data within an aperture by a smooth function of the dispersion +coordinate. Unlike the extraction tasks the output of this algorithm is +a two dimensional image of the same format as the input image. This function +is used primarily for creating flat field images in which the large +scale shape of the quartz spectra and the variations in level between the +spectra are removed and the regions between the spectra, where there is no +signal, are set to unity. It may also be used to normalize two dimensional +spectra to a unit continuum at some point in the spectrum, such as the center. +.PP +The algorithm is to extract a one dimensional spectrum for each aperture, +fit a smooth function to the spectrum, and then divide this spectrum +back into the two dimensional image. Points outside the apertures are +set to 1. This is the same algorithm used in the \fBlongslit\fR package +by the task \fBresponse\fR except that it applies to arbitrary apertures +rather than to image sections. +.PP +Apertures are defined in the same way as for extraction. The normalization +spectrum may be obtained from a different aperture than the aperture to be +normalized. Generally the normalization apertures are either the same or +narrower than the apertures to be normalized. The continuum fitting also +uses the \fBicfit\fR package. Sample regions and iterative sigma clipping +are used to remove spectral lines from the continuum fits. +.PP +There are two commonly used approaches to fitting the extracted spectra +in flat field images. First, a constant function is fit. This has the +effect of simply normalizing the apertures to near unity without affecting +the shape of spectra in any way. This removes response effects at all scales, +from spectra flatten with this flat field. However, it does not +preserve total counts, it introduces the shape of the quartz spectrum, +and it removes the blaze function. The second approach is to fit the +large scale shape of the quartz spectra. This removes smaller scale +response effects such a fringing and individual pixel responses while +preserving the total counts by leaving the blaze function alone. There are +cases where each of these approaches is applicable. +.NH +Apertures +.PP +Apertures are the basic data structures used in the package; hence the +package name. An aperture defines a region of the two dimensional image +to be extracted. The aperture definitions are stored in a database. +An aperture consists of the following components: + +.IP ID +.br +An integer identification number. The identification number must be +unique. It is used as the default extension during extraction of +the spectra. Typically the IDs are consecutive positive integers +ordered by increasing or decreasing slit position. +.IP BEAM +.br +An integer beam number. The beam number need not be +unique; i.e. several apertures may have the same beam number. +The beam number will be recorded in the image header of the +the extracted spectrum. By default the beam number is the same as +the ID. +.IP CENTER[2] +.br +The center of the aperture along the slit and dispersion axes in the two +dimensional image. +.IP LOWER[2] +.br +The lower limits of the aperture, relative to the aperture center, +along the slit and dispersion axes. The lower limits need not be less +than the center. +.IP UPPER[2] +.br +The upper limits of the aperture, relative to the aperture center, +along the slit and dispersion axes. The upper limits need not be greater +than the center. +.IP APAXIS +.br +The aperture or spatial axis. +.IP CURVE +.br +An offset to be added to the center position for the aperture axis as +a function of the wavelength. The function is one of the standard IRAF +types; a legendre polynomial, a chebyshev polynomial, a linear spline, +or a cubic spline. +.IP BACKGROUND +.br +Parameters for background subtraction along the aperture axis based on +the interactive curve fitting (\fBicfit\fR) tools. + +.PP +The aperture center is the only absolute coordinate (relative to the +image or image section). The other aperture parameters and the +background fitting regions are defined relative to the center. Thus, +an aperture may be repositioned easily by changing the center +coordinates. Also constant aperture size, shape (curve), and +background regions may be maintained for many apertures. +.PP +The edges of the aperture along the spatial axis at each point along the +dispersion axis are given by evaluating the offset curve at that dispersion +coordinate and adding the aperture center and the lower or upper limits +for the aperture axis. The edges of the aperture along the dispersion axis +do not have an offset curve and are currently fixed to define the entire +length of the image. In the future this may not be the case such as +in applications with objective prism spectra. +.PP +Apertures for a particular image may be defined in several ways. They +may be defined and modified graphically with an aperture editor. Default +apertures may be defined automatically with parameters from the +\fBapdefault\fR pset using an aperture finding algorithm. Another +method is to specify that the apertures for one image use the aperture +definitions from another "reference" image. In the rare cases where +apertures are not defined at the stage of tracing or extracting then +a single default aperture centered in the image is created. +.NH 2 +The Database +.PP +The aperture information is stored in a database. The structure and type of +database is expected to change in the future and as far as the package and +user need be concerned it is just a black box with some name specified in +the database name parameter. However, accepting that the database structure may +change it may be of use to the user to understand the nature of the current +text file / directory format database. The database is a directory containing +text files. It is automatically created if necessary. The aperture data +for all the apertures from a single image are stored in a text file +with the name given by the image name (with special characters replaced +with '_') prefixed with "ap". Updates of the aperture data are performed +by overwriting the database file. +.PP +The content of a file consists of a comment (beginning with a #) giving +the date created/updated, a record identification (there is one record +per aperture) with the image name, aperture number and aperture +coordinate in the aperture and dispersion axes. The following lines +give information about the aperture. The position and shape of an +aperture is given by a center coordinate along the aperture axis (given +by the axis keyword) and the dispersion axis. There are lower and +upper limits for the aperture relative to this center, again along both +axis. Currently the limits along the dispersion axis are the image +boundaries. The background keyword introduces the background +subtraction parameters. Finally there is an offset or trace function +which is added to the center at each point along the dispersion axis. +function. The offset is generally zero at the dispersion point +corresponding to the aperture center. +.PP +This offset or trace function is described by a \fBcurfit\fR array under +the keyword curve. The first value is the number of elements in this +array. The first element is a magic number specifying the function +type. The next number is the order or number of spline pieces. The +next two elements give the range over which the curve is defined. In +the \fBapextract\fR case it is the edges of the image along the dispersion. +The remaining elements are the function coefficients. The form of the +the function is specific to the IRAF \fBcurfit\fR math routines. Note that +the coefficients apply to an independent variable which is -1 at the +beginning of the defined range (element 3) and 1 at the end of the range +(element 4). For further details consult the IRAF group. +.PP +An example database file for one aperture from an image "ech001" is given +below. + +.ft L +.nf + # Fri 14:33:35 08-May-87 + begin aperture ech001 1 22.75604 100. + image ech001 + aperture 1 + beam 1 + center 22.75604 100. + low -2.680193 -99. + high 3.910698 100. + background + xmin -262. + xmax 262. + function chebyshev + order 1 + sample -10:-6,6:10 + naverage -3 + niterate 0 + low_reject 3. + high_reject 3. + grow 0. + axis 1 + curve 6 + 2. + 2. + 1. + 200. + -0.009295368 + -0.3061974 +.fi +.ft R +.NH +Future Developments +.PP +The IRAF extraction package \fBapextract\fR is going to continue to +evolve because the extraction of one and two dimensional spectra +from two dimensional images is an important part of reducing echelle, +longslit, multislit, and multiaperture spectra. Changes may include +some of the following: + +.IP (1) +Determine the actual variance from the data rather than using the Poisson +CCD model. Also output the variance vector if desired. +.IP (2) +The bad pixel detection and removal algorithm does not handle well the case +of a very strong cosmic ray event on top of a very weak spectrum profile. +A heuristic method to make the first fitting pass of the average +profile to the image data less prone to errors due to strong cosmic rays +is needed. Also the detection should be done by interpolating the profile +to the original image data rather than the other way around, in order to +avoid broadening cosmic rays by interpolation. +.IP (3) +The aperture definition structure is general enough to allow the aperture +limits along the dispersion dimension to be variable. Eventually aperture +definition and editing will be available using an image display. Then +both graphics and image display editing switches will be available. +An image display interface will make extraction of objective prism +spectra more convenient than it is now. +.IP (4) +Other types of extraction weighting may be added. diff --git a/noao/twodspec/apextract/doc/old/apextract2.ms b/noao/twodspec/apextract/doc/old/apextract2.ms new file mode 100644 index 00000000..35b42390 --- /dev/null +++ b/noao/twodspec/apextract/doc/old/apextract2.ms @@ -0,0 +1,14 @@ +.RP +.TL +Cleaning and Optimal Extraction with the IRAF APEXTACT Package +.AU +Francisco Valdes +.AI +IRAF Group - Central Computer Services +.K2 +P.O. Box 26732, Tucson, Arizona 85726 +.AB +.AE +.NH +Introduction +.PP diff --git a/noao/twodspec/apextract/doc/revisions.v3.ms b/noao/twodspec/apextract/doc/revisions.v3.ms new file mode 100644 index 00000000..f78362a5 --- /dev/null +++ b/noao/twodspec/apextract/doc/revisions.v3.ms @@ -0,0 +1,522 @@ +.nr PS 9 +.nr VS 11 +.RP +.ND +.TL +APEXTRACT Package Revisions Summary: IRAF Version 2.10 +.AU +Francisco Valdes +.AI +IRAF Group - Central Computer Services +.K2 +P.O. Box 26732, Tucson, Arizona 85726 +September 1990 +.AB +This paper summarizes the changes in Version 3 of the IRAF \fBapextract\fR +package which is part of IRAF Version 2.10. The major new features and +changes are: + +.IP \(bu +New techniques for cleaning and variance weighting extracted spectra +.IP \(bu +A new task, \fBapall\fR, which integrates all the parameters used for +one dimensional extraction of spectra +.IP \(bu +A new extended output format for recording both weighted and unweighted +extractions, subtracted background, and variance information. +.IP \(bu +Special featurers for automatically numbering and identifying large +numbers of apertures. +.IP \(bu +New tasks and algorithms, \fBaprecenter\fR and \fBapresize\fR, +for automatically recentering and resizing aperture definitions +.IP \(bu +A new task, \fBapflatten\fR, for creating flat fields from +fiber and slitlet spectra +.IP \(bu +A new task, \fBapfit\fR, providing various types of fitting for +two dimensional multiobject spectra. +.IP \(bu +A new task, \fBapmask\fR, for creating mask images from aperture definitions. +.AE +.NH +Introduction +.PP +A new version of the IRAF \fBapextract\fR package has been completed. +It is Version 3 and is part of IRAF Version 2.10. The package will +be made available as an external package prior to the release of V2.10. +This paper describes the changes and new features of the package. It +does not describe them in detail. Full details of the algorithms, +functions, and parameters are found in the task descriptions. +Reference is made to the previous version so familiarity with that +version is useful though not necessary. There were three goals for the +new package: new and improved cleaning and variance weighting (optimal +extraction) algorithms, the addition of recommended or desirable new +tasks and algorithms (particularly to support large numbers of spectra +from fiber and aperture mask instruments), and special support for the +new image reduction scripts. Features relating to the last point are +not discussed here. +.PP +Table 1 summarizes the major new features and changes in the package. + +.ce +Table 1: Summary of Major New Features and Changes + +.IP \(bu +New techniques for cleaning and variance weighting extracted spectra +.IP \(bu +A new task, \fBapall\fR, which integrates all the parameters used for +one dimensional extraction of spectra +.IP \(bu +A new extended output format for recording both weighted and unweighted +extractions, subtracted background, and variance information. +.IP \(bu +Special featurers for automatically numbering and identifying large +numbers of apertures. +.IP \(bu +New tasks and algorithms, \fBaprecenter\fR and \fBapresize\fR, for +automatically recentering and resizing aperture definitions +.IP \(bu +A new task, \fBapflatten\fR, for creating flat fields from fiber and slitlet +spectra +.IP \(bu +A new task, \fBapfit\fR, providing various types of fitting for two dimensional +multiobject spectra. +.IP \(bu +A new task, \fBapmask\fR, for creating mask images from aperture definitions. +.NH +Cleaned and Variance Weighted Extractions: apsum and apall +.PP +There are two types of aperture extraction (estimating the background +subtracted flux across a fixed width aperture at each image line or +column) just as in the previous version. One is a simple sum of pixel +values across an aperture. In the previous version this was called +"profile" weighting while in this version it is simply called +unweighted or "none". The second type weights each pixel in the sum by +its estimated variance based on a spectrum model and detector noise +parameters. As before this type of extraction is selected by +specifying "variance" for the weighting parameter. +.PP +Variance weighting is often called "optimal" extraction since it +produces the best unbiased signal-to-noise estimate of the flux in the +two dimensional profile. It also has the advantage that wider +apertures may be used without penalty of added noise. The theory and +application of this type of weighting has been described in several +papers. The ones which were closely examined and used as a model for +the algorithms in this software are \fIAn Optimal Extraction Algorithm +for CCD Spectroscopy\fR, \fBPASP 98\fR, 609, 1986, by Keith Horne and +\fIThe Extraction of Highly Distorted Spectra\fR, \fBPASP 100\fR, 1032, +1989, by Tom Marsh. +.PP +The noise model for the image data used in the variance weighting, +cleaning, and profile fitting consists of a constant gaussian noise and +a photon count dependent poisson noise. The signal is related to the +number of photons detected in a pixel by a gain parameter given +as the number of photons per data number. The gaussian noise is given +by a readout noise parameter which is a defined as a sigma in +photons. The poisson noise is approximated as gaussian with sigma +given by the number of photons. The method of specifying this noise +model differs from the previous version in that the more common CCD +detector parameters of readout noise and gain are used rather than the +linear variance parameters "v0" and "v1". +.PP +Some additional effects which should be considered in principle, and +which are possibly important in practice, are that the variance +estimate should be based on the actual number of photons detected before +correction for pixel sensitivity; i.e. before flat field correction. +Furthermore the uncertainty in the flat field should also be included +in the weighting. However, the profile must be determined free of +sensitivity effects including rapid larger scale variations such as +fringing. Thus, ideally one should input the unflat-fielded +observation and the flat field data and carry out the extractions with +the above points in mind. However, due to the complexity often +involved in basic CCD reductions and special steps required for +producing spectroscopic flat fields this level of sophistication is not +provided by the current package. +.PP +The package does provide, however, for propagation of an approximate +uncertainty in the background estimate when using background subtraction. +If background subtraction is done, a background variance is computed +using the poisson noise model based on the estimated background counts. +Because the background estimate is based on a finite number of +pixels, the poisson variance estimate is divided by the number (minus +one) of pixels used in determining the background. The number of +pixels used includes any box car smoothing. Thus, the larger the +number of background pixels the smaller the background noise +contribution to the variance weighting. This method is only +approximate since no correction is made for the number of degrees of +freedom and correlations when using the fitting method of background +estimation. +.PP +If removal of cosmic rays and other deviant pixels is desired (called +cleaning) they are iteratively rejected based on the estimated variance +and excluded from the weighted sum. Unlike the previous version, a +cleaned extraction is always variance weighted. This makes sense since +the detector noise parameters must be specified and the spectrum +profile computed, so all of the computational effort must be done +anyway, and the variance weighting is as good or superior to a simple +unweighted extraction. +.PP +The detection and removal of deviant pixels is straightforward. Based +on the noise model, pixels deviating by more than a +specified number of sigma (square root of the variance) above or below +the model are removed from the weighted sum. A new spectrum estimate +is made and the rejection is repeated. The rejections are made one at +a time starting with the most deviant and up to half the pixels in the +aperture may be rejected. +.NH +Spectrum Profile Determination: apsum, apall, apflatten, apfit +.PP +The foundation of variance weighted or optimal extraction, cosmic ray +detection and removal, two dimensional flat field normalization, and +spectrum fitting and modeling is the accurate determination of the +spectrum profile across the dispersion as a function of wavelength. +The previous version of the \fBapextract\fR package accomplished this by +averaging a specified number of profiles in the vicinity of each +wavelength after correcting for shifts in the center of the profile. +This technique was sensitive to perturbations from cosmic rays +and the exact choice of averaging parameters. The current version of +the package uses a different algorithm, actually a combination of +two algorithms, which is much more stable. +.PP +The basic idea is to normalize each profile along the dispersion to +unit flux and then fit a low order function to sets of unsaturated +points at nearly the same point in the profile parallel to the +dispersion. The important point here is that points at the same +distance from the profile center should have the nearly the same values +once the continuum shape and spectral features have been divided out. +Any variations are due to slow changes in the shape of the profile with +wavelength, differences in the exact point on the profile, pixel +binning or sampling, and noise. Except for the noise, the variations +should be slow and a low order function smoothing over many points will +minimize the noise and be relatively insensitive to bad pixels such as +cosmic rays. Effects from bad pixels may be further eliminated by +chi-squared iteration and clipping. Since there will be many points +per degree of freedom in the fitting function the clipping may even be +quite aggressive without significantly affecting the profile +estimates. Effects from saturated pixels are minimized by excluding +from the profile determination any profiles containing one or more +saturated pixels. +.PP +The normalization is, in fact, the one dimensional spectrum. Initially +this is the simple sum across the aperture which is then updated +by the variance weighted sum with deviant pixels possibly removed. +This updated one dimensional spectrum is what is meant by the +profile normalization factor in the discussion below. The two dimensional +spectrum model or estimate is the product of the normalization factor +and the profile. This model is used for estimating +the pixel intensities and, thence, the variances. +.PP +There are two important requirements that must be met by the profile fitting +algorithm. First it is essential that the image data not be +interpolated. Any interpolation introduces correlated errors and +broadens cosmic rays to an extent that they may be confused with the +spectrum profile, particularly when the profile is narrow. This was +one of the problems limiting the shift and average method used +previously. The second requirement is that data fit by the smoothing +function vary slowly with wavelength. This is what precludes, for +instance, fitting profile functions across the dispersion since narrow, +marginally sampled profiles require a high order function using only a +very few points. One exception to this, which is sometimes useful but +of less generality, is methods which assume a model for the profile +shape such as a gaussian. In the methods used here there is no +assumption made about the underlying profile other than it vary +smoothly with wavelength. +.PP +These requirements lead to two fitting algorithms based on how well the +dispersion axis is aligned with the image columns or lines. When the +spectra are well aligned with the image axes one dimensional functions +are fit to the image columns or lines. Small excursions of a few +pixels over the length of the spectrum can be adequately fit in this +way. When the spectra become strongly tilted then single lines or +columns may cross the actual profile relatively quickly causing the +requirement of a slow variation to be violated. One thought is to use +interpolation to fit points always at the same distance from the +profile. This is ruled out by the problems introduced by image +interpolation. However, there is a clever method which, in effect, +fits low order polynomials parallel to the direction defined by tracing +the spectrum but which does not interpolate the image data. Instead it +weights and couples polynomial coefficients. This method was developed +by Tom Marsh and is described in detail in the paper, \fIThe Extraction +of Highly Distorted Spectra\fR, \fBPASP 101\fR, 1032, Nov. 1989. Here +we refer to this method as the Marsh algorithm and do not attempt to +explain it further. +.PP +Both fitting algorithms weight the pixels by their variance as computed +from the background and background variance if background subtraction +is specified, the spectrum estimate from the profile and the spectrum +normalization, and the detector noise parameters. The noise model is +that described earlier. +.PP +The profile fitting can be iterated to remove deviant pixels. This is +done by rejecting pixels greater than a specified number of sigmas +above or below the expected value based on the profile, the +normalization factor, the background, the detector noise parameters, +and the overall chi square of the residuals. Rejected points are +removed from the profile normalization and from the fits. +.NH +New Extraction Task: apall +.PP +All of the functions of the \fBapextract\fR package are actually part +of one master program. The organization of the package into tasks by +function with parameters to allow selection of some of the other +functions, for example the aperture editor may be entered from +virtually every task, was done to highlight the logic and organize the +parameters into small sets. However, there was often confusion about +which parameters were being used and the need to set parameters in one +task, say \fBaptrace\fR, in order to use the trace option in another +task, say \fBapsum\fR. In practice, for the most common function of +extraction of two dimensional spectra to one dimension most users end up +using \fBapsum\fR for all the functions. +.PP +In the new version, the old organization is retained (with the addition +of new functions and some changes in parameters) but a new task, +\fBapall\fR, is also available. This task contains all of the +parameters needed for extraction with a parameter organization which is +nicely formated for use with \fBeparam\fR. The parameters in +\fBapall\fR are independent of the those in the other tasks. It is +expected that many, if not most users will opt to use this task for +spectrum extraction in preference to the individual functions. +.PP +The organization by function is still used in the documentation. This +is still the best way to organize the descriptions of the various +algorithms and parameters. As an example, the profile tracing algorithm +is described in most detail under the topic \fBaptrace\fR. +.NH +Extraction Output Formats: apsum and apall +.PP +The extracted spectra are recorded in one, two, or three dimensional +images depending on the \fIformat\fR and \fIextras\fR parameters. If +the \fIextras\fR parameter is selected the formats are three +dimensional with each plane in the third dimension containing +associated information for the spectra in the first plane. This +information includes the unweighted spectrum and a sigma spectrum +(estimated from the variances and weights of the pixels extracted) when +using variance weighting, and the background spectrum when background +subtraction is used. When \fIextras\fR is not selected only the +extracted spectra are output. +.PP +The formats are basically the same as in the previous version; +onedspec, multispec, and echelle. In addition, the function of the +task \fBapstrip\fR in the previous version has been transferred to the +extraction tasks by simply specifying "strip" for the format. +.PP +There are some additions to the header parameters in multispec and +echelle format. Two additional fields have been added to the +aperture number parameter giving the aperture limits (at the reference +dispersion point). Besides being informative it may be used for +interpolating dispersion solutions spatially. A second, optional keyword per +spectrum has been added to contain a title. This is useful for +multiobject spectra. +.NH +Easier and Extended Aperture Identifications: apfind and apedit +.PP +When dealing with a large number of apertures, such as occur with +multifiber and multiaperture data, the burden of making and maintaining +useful aperture identifications becomes large. Several very useful +improvements were made in this area. These improvements generally +apply equally to aperture identifications made by the automated +\fBapfind\fR algorithm and those made interactively using +\fBapedit\fR. In the simplest usage of defining apertures +interactively or with the aperture finding algorithm, aperture numbers +are assigned sequentially beginning with 1. In the new version the +parameter "order" allows the direction of increasing aperture numbers +with respect to the direction of increasing pixel coordinate (either +column or line) to be set. An "increasing" order parameter value +numbers the apertures from left to right (the direction naturally +plotted) in the same sense as the pixel coordinates. A "decreasing" +order reverses this sense. +.PP +Some instruments, particularly multifiber instruments, produce nearly +equally spaced spectra for which one wants to maintain a consistent +numbering sequence. However, at times some spectra may be missing +due to broken or unassigned fibers and one would like to skip an +aperture identification number to maintain the same fiber assignments. +To do this automatically, a new parameter called \fImaxsep\fR has been +added. This parameter defines the maximum separation between two +apertures beyond which a jump in the aperture sequence is made. In +other words the sequence increment is given by rounding down the +separation divided by this parameter. How accurately this value has +to be specified depends on how large the gaps may be and the natural +variability in the aperture positions. In conjunction with the +minimum separation parameter this algorithm works quite well in +accounting for missing spectra. +.PP +One flaw in this scheme is when the first spectrum is missing causing +the identifications will be off. In this case the modified interactive +aperture editing command 'o' asks for the aperture identification +number of the aperture pointed at by the cursor and then automatically +renumbers the other apertures relative to that aperture. The other +possible flaw is identification of noise as a spetrum but this is +controlled by the \fIthreshold\fR parameter and, provided the actual +number of spectra is known, say by counting off a graph, then the +\fInfind\fR parameter generally limits this type of problem. +.PP +A new attribute of an aperture is a title. If present this title +is propagated through the extraction into the image headers. The title +may be set interactively but normally the titles are supplied in +another new feature, an "aperture identification" file specified by +the parameter \fIapidtable\fR. This file provides +the most flexibility in making aperture identification assignments. +The file consists of lines with three fields, a unique aperture number, +a beam or aperture type number which may be repeated, and the +aperture title. The aperture identification lines from the file are +assigned sequentially in the same order as would be done if using +the default indexing including skipping of missing spectra based on +the maximum separation. +.PP +By default the beam number is the same as the aperture number. When +using an aperture identification file the beam number can be used +to assign spectrum types which other software may use. For example, +some of the specialized fiber reduction packages use the beam number +to identify sky fibers and embedded arc fibers. +.NH +New Aperture Recentering Task: aprecenter +.PP +An automated recentering algorithm has been added. It may be called +through the new \fBaprecenter\fR command, from any of the tasks containing +the \fIrecenter\fR parameter, or from the aperture editor. The purpose of +this new feature is to allow automatically adjusting the aperture +centers to follow small changes in the positions of spectra expected to be at +essentially the same position, such as with fiber fed spectrographs. +This does not change the shape of the trace but simply adds a shift +across the dispersion axis. +.PP +Typically, one uses a strong image to define reference apertures and +then for subsequent objects uses the reference positions with a +recentering to correct for flexure effects. However, it may be +inappropriate to base a new center on weak spectra or to have multiple +spectra recentered independently. The recentering options provide for +selecting specific apertures to be recentered, selecting only a +fraction of the strongest (highest peak data level) spectra and +averaging the shifts determined (possible from only a subset of the +spectra) and applying the average shift to all the apertures. +Note that one may still specify the dispersion line and number of +dispersion lines to sum in order to improve the signal for centering. +.NH +New Aperture Resizing Task: apresize +.PP +An automated resizing algorithm has been added. It may be called +through the new \fBapresize\fR command, from any of the tasks +containing the \fIresize\fR parameter, or from the aperture editor with +the new key 'z' (the y cursor level command is still available with the +'y' key). The purpose of this new feature is to allow automatically +adjusting the aperture widths to follow changes in seeing and to +provide a greater variety of global aperture sizing methods. +.PP +In all the methods the aperture limits are set at the pixel positions +relative to the center which intersect the linearly interpolated data +at some data value. The methods differ in how the data level is +determined. The methods are: + +.IP \(bu +Set size at a specified absolute data level +.IP \(bu +Set size at a specified data level above a background +.IP \(bu +Set size at a specified fraction of the peak pixel value +.IP \(bu +Set size at a specified fraction of the peak pixel value above a background +.LP +The automatic background is quite simple; a line connecting the first +local minima from the aperture center. +.PP +The limits determined by one of the above methods may be further +adjusted. The limits may be increased or decreased by a specified +fraction. This allows setting wider limits based on more accurately +determined limits from the stronger part of the profile; for example +doubling the limits obtained from the half intensity point. A maximum +extent may be imposed. Finally, if there is more than one aperture and one +wants to maintain the same aperture size, the apertures sizes +determined individually may be averaged and substituted for all the +apertures. +.NH +New Aperture Mask Output: apmask +.PP +A new task, \fBapmask\fR, has been added to produce a mask file/image +of 1's and 0's defined by the aperture definitions. This is based on +the new IRAF mask facilities. The output is a compact binary file +which may be used directly as an image in most applications. In +particular the mask file can be used with tasks such as \fBimarith\fR, +\fBimreplace\fR, and \fBdisplay\fR. Because the mask facility is new, +there is little that can be done with masks other than using it as an +image. However, eventually many tasks will be able to use mask +images. The aperture mask will be particularly well suited to work +with \fBimsurfit\fR for fitting a surface to the data outside the apertures. +This would be an alternative for scattered light modeling to the +\fBapscatter\fR tasks. +.NH +Aperture Flat Fields and Normalization: apflatten and apnormalize +.PP +Slitlet, echelle, and fiber spectra have the characteristic that the +signal falls off to near zero values outside regions of the image +containing spectra. Also fiber profiles are usually undersampled +causing problems with gradients across the pixels. Directly dividing +by a flat field produces high noise (if not division by zero) where the +signal is low, introduces the spectrum of the flat field light, and +changes the profile shape. +.PP +One method for modifying the flat field to avoid these problems is +provided by the task \fBimred.generic.flat1d\fR. However, this task +does not use any knowledge of where the spectra are. There are two +tasks in the \fBapextract\fR package which can be used to modify flat +field images. \fBapnormalize\fR is not new. It divides the spectra +within specified apertures by a one dimensional spectrum, either a +constant for simple throughput normalization or some smoothed version +of the spectrum in the aperture to remove the spectral shape. Pixels +outside specified apertures are set to unity to avoid division +effects. This task has the effect of preserving the profile shape in +the flat field which may be desired for attempts to remove slit +profiles. +.PP +Retaining the profile shape of the flat field can give very bad edge +effects, however, if there is image flexure. A new task similar to +\fBflat1d\fR but which uses aperture information is \fBapflatten\fR. +It uses the spectrum profile model described earlier. For nearly image +axes aligned spectra this amounts very nearly to the line or column +fitting of \fBflat1d\fR. As with \fBapnormalize\fR there is an option +to fit the one dimensional spectrum to remove the large scale shape of +the spectrum while preserving small scale sensitivity variations. The +smoothed spectrum is multiplied by the normalized profile and divided +into the data in each aperture. Pixels outside the aperture are set to +1. Pixels with model values below a threshold are also set to 1. This +produces output images which have the small scale sensitivity +variations, a normalized mean, and the spectrum profile removed. +.NH +Two Dimensional Spectrum Fitting: apfit +.PP +The profile and spectrum fitting used for cleaning and variance +weighted extraction may be used and output in the new task +\fBapfit\fR. The task \fBapfit\fR is similar in structure to +\fBfit1d\fR. One may output the fit, difference, or ratio. The fit +may be used to examine the spectrum model used for the cleaning and +variance weighted extraction. The difference and ratio may used to +display small variations and any deviant pixels. While specific uses +are not given this task will probably be used in interesting ways not +anticipated by the author. +.NH +I/O and Dispersion Axis Parameters: apextract and apio +.PP +The general parameters, primarily concerning input and output devices +and files, were previously in the parameter set \fBapio\fR. This "pset" +task has been removed and those parameters are now found as part of +the package parameters, i.e. \fBapextract\fR. There is one new parameter +in the \fBapextract\fR package parameters, dispaxis. In the previous +version of the package one needed to run the task \fBsetdisp\fR to insert +information in the image header identifying the dispersion direction +of the spectra in the image. Often people would forget this step +and receive an error message to that effect. The new parameter +allows skipping this step. If the DISPAXIS image header parameter +is missing the package parameter value is inserted into the image +header as part of the processing. Note that if the parameter is +present in the image header either because \fBsetdisp\fR was used or the +image creation process inserted it (a future ideal case) then that +value is used in preference to the package parameter. +.NH +Strip Extraction: apstrip +.PP +The task \fBapstrip\fR from the previous version has been removed. +However, it is possible to obtain two dimensional strips aligned with +the image axes by specifying a format of "strip" when using \fBapsum\fR +or \fBapall\fR. While the author doesn't anticipate a good scientific +use for this feature others may find it useful. diff --git a/noao/twodspec/apextract/mkpkg b/noao/twodspec/apextract/mkpkg new file mode 100644 index 00000000..bcc342c4 --- /dev/null +++ b/noao/twodspec/apextract/mkpkg @@ -0,0 +1,76 @@ +# APEXTRACT + +$call relink +$exit + +update: + $call relink + $call install + ; + +relink: + $update libpkg.a + $call apextract + ; + +install: + $move xx_apextract.e noaobin$x_apextract.e + ; + +apextract: + $omake x_apextract.x + $link x_apextract.o libpkg.a -lxtools\ + -lcurfit -liminterp -lllsq -o xx_apextract.e + ; + +libpkg.a: + apalloc.x apertures.h + apanswer.x + apcenter.x <pkg/center1d.h> + apcolon.x apertures.h <error.h> <gset.h> <imhdr.h> + apcopy.x apertures.h + apcveval.x <math/curfit.h> + apcvset.x apertures.h <math/curfit.h> + apdb.x apertures.h <math/curfit.h> <pkg/dttext.h> + apdefault.x apertures.h <imhdr.h> + apdelete.x + apedit.x apertures.h <gset.h> <imhdr.h> <mach.h> <pkg/gtools.h> + apextract.x apertures.h <error.h> <imhdr.h> <mach.h>\ + <math/iminterp.h> <pkg/gtools.h> + apfind.x apertures.h <imhdr.h> <mach.h> + apfindnew.x apertures.h <mach.h> + apfit.x apertures.h <imhdr.h> <imset.h> <pkg/gtools.h> + apgetdata.x <imhdr.h> + apgetim.x + apgmark.x apertures.h <pkg/rg.h> + apgraph.x apertures.h <pkg/gtools.h> + apgscur.x apertures.h + apicset.x apertures.h <imhdr.h> + apids.x apertures.h <error.h> <mach.h> + apimmap.x <imhdr.h> + apinfo.x apertures.h + apio.x <time.h> + apmask.x apertures.h <imhdr.h> <pmset.h> + apmw.x <error.h> <imhdr.h> <imio.h> <mwset.h> + apnearest.x apertures.h <mach.h> + apnoise.x apertures.h <gset.h> <pkg/gtools.h> + apparams.x + appars.x <math/iminterp.h> + apprint.x apertures.h + approfile.x apertures.h <gset.h> <mach.h> <math/curfit.h> + aprecenter.x apertures.h + apresize.x apertures.h + apscatter.x apertures.h <error.h> <imhdr.h> <imset.h> <pkg/gtools.h> + apselect.x apertures.h + apshow.x apertures.h + apskyeval.x apertures.h <math/iminterp.h> <mach.h> + apsort.x apertures.h + aptrace.x apertures.h <imhdr.h> <math/curfit.h> <pkg/center1d.h>\ + <pkg/gtools.h> + apupdate.x apertures.h <gset.h> + apvalues.x apertures.h + apvariance.x apertures.h <gset.h> + apylevel.x + peaks.x + t_apall.x apertures.h <error.h> <imhdr.h> <pkg/gtools.h> + ; diff --git a/noao/twodspec/apextract/peaks.x b/noao/twodspec/apextract/peaks.x new file mode 100644 index 00000000..fe525f88 --- /dev/null +++ b/noao/twodspec/apextract/peaks.x @@ -0,0 +1,313 @@ +# PEAKS -- The following procedures are general numerical functions +# dealing with finding peaks in a data array. +# +# FIND_PEAKS Find additional peaks in the data array. +# FIND_LOCAL_MAXIMA Find the local maxima in the data array. +# IS_LOCAL_MAX Test a point to determine if it is a local maximum. +# FIND_CONTRAST Find the peaks satisfying the contrast constraint. +# FIND_ISOLATED Flag peaks which are within separation of a peak +# with a higher peak value. +# FIND_NMAX Select up to the nmax highest ranked peaks. +# COMPARE Compare procedure for sort used in FIND_PEAKS. + +# FIND_PEAKS -- Find the peaks in the data array. +# +# The peaks are found using the following algorithm: +# +# 1. Find the local maxima which are not near the edge of existing peaks. +# 2. Reject those below the absolute threshold. +# 3. Reject those below the contrast threshold. +# 4. Determine the ranks of the remaining peaks. +# 5. Flag weaker peaks within separation of a stronger peak. +# 6. Add strongest peaks to the peaks array. +# +# Indefinite data points are ignored. + +procedure find_peaks (data, npts, contrast, edge, nmax, separation, threshold, + peaks, npeaks) + +real data[npts] # Input data array +int npts # Number of data points + +real contrast # Maximum contrast between strongest and weakest +int edge # Minimum distance from the edge +int nmax # Maximum number of peaks to be returned +real separation # Minimum separation between peaks +real threshold # Minimum threshold level for peaks + +real peaks[nmax] # Positons of input peaks / output peaks +int npeaks # Number of input peaks / number of output peaks + +int i, nx +pointer sp, x, y, rank + +int compare() +extern compare() + +common /sort/ y + +begin + if (npeaks >= nmax) + return + + call smark (sp) + call salloc (x, npts, TY_INT) + call salloc (y, npts, TY_REAL) + + # Find the positions of the local maxima. + call find_local_maxima (data, npts, peaks, npeaks, edge, separation, + threshold, Memi[x], Memr[y], nx) + + # Eliminate points not satisfying the contrast constraint. + call find_contrast (data, Memi[x], Memr[y], nx, contrast) + + # Rank the peaks by peak value. + call salloc (rank, nx, TY_INT) + for (i = 1; i <= nx; i = i + 1) + Memi[rank + i - 1] = i + call qsort (Memi[rank], nx, compare) + + # Reject weaker peaks within a specified separation of a stronger peak. + call find_isolated (Memi[x], Memi[rank], nx, separation) + + # Add the strongest peaks. + call find_nmax (Memi[x], Memi[rank], nx, nmax, peaks, npeaks) + + call sfree (sp) +end + + +# FIND_LOCAL_MAXIMA -- Find the local maxima in the data array. + +procedure find_local_maxima (data, npts, peaks, npeaks, edge, separation, + threshold, x, y, nx) + +real data[npts] # Input data array +int npts # Number of input points +real peaks[ARB] # Positions of peaks +int npeaks # Number of peaks +int edge # Edge buffer distance +real separation # Minimum separation from peaks +real threshold # Data threshold +int x[npts] # Output positions +real y[npts] # Output data values +int nx # Number of maxima + +int i, j + +bool is_local_max() + +begin + # Find the local maxima above the threshold and not near the edge. + nx = 0 + for (i = edge + 1; i <= npts - edge; i = i + 1) { + if ((data[i] >= threshold) && (is_local_max (i, data, npts))) { + nx = nx + 1 + x[nx] = i + } + } + + # Flag maxima within separation of previous peaks. + for (j = 1; j <= npeaks; j = j + 1) { + for (i = 1; i <= nx; i = i + 1) { + if (IS_INDEFI (x[i])) + next + if (x[i] < peaks[j] - separation) + next + if (x[i] > peaks[j] + separation) + break + x[i] = INDEFI + } + } + + # Eliminate flagged maxima and set y values. + j = 0 + for (i = 1; i <= nx; i = i + 1) { + if (!IS_INDEFI (x[i])) { + j = j + 1 + x[j] = x[i] + y[j] = data[x[j]] + } + } + + nx = j +end + + +# IS_LOCAL_MAX -- Test a point to determine if it is a local maximum. +# +# Indefinite points are ignored. + +bool procedure is_local_max (index, data, npts) + +# Procedure parameters: +int index # Index to test for local maximum +real data[npts] # Data values +int npts # Number of points in the data vector + +int i, j, nright, nleft + +begin + # INDEFR points cannot be local maxima. + if (IS_INDEFR (data[index])) + return (false) + + # Find the left and right indices where data values change and the + # number of points with the same value. Ignore INDEFR points. + nleft = 0 + for (i = index - 1; i >= 1; i = i - 1) { + if (!IS_INDEFR (data[i])) { + if (data[i] != data[index]) + break + nleft = nleft + 1 + } + } + nright = 0 + for (j = index + 1; i <= npts; j = j + 1) { + if (!IS_INDEFR (data[j])) { + if (data[j] != data[index]) + break + nright = nright + 1 + } + } + + # Test for failure to be a local maxima + if ((i == 0) && (j == npts)) { + return (FALSE) # Data is constant + } else if (i == 0) { + if (data[j] > data[index]) + return (FALSE) # Data increases to right + } else if (j == npts) { + if (data[i] > data[index]) # Data increase to left + return (FALSE) + } else if ((data[i] > data[index]) || (data[j] > data[index])) { + return (FALSE) # Not a local maximum + } else if (!((nleft - nright == 0) || (nleft - nright == 1))) { + return (FALSE) # Not center of plateau + } + + # Point is a local maxima + return (TRUE) +end + + + +# FIND_CONTRAST -- Find the peaks with positions satisfying contrast constraint. + +procedure find_contrast (data, x, y, nx, contrast) + +real data[ARB] # Input data values +int x[ARB] # Input/Output peak positions +real y[ARB] # Output peak data values +int nx # Number of peaks input +real contrast # Contrast constraint + +int i, j +real minval, maxval, threshold + +begin + if ((nx == 0.) || (contrast <= 0.)) + return + + call alimr (y, nx, minval, maxval) + threshold = contrast * maxval + + j = 0 + do i = 1, nx { + if (y[i] < threshold) { + j = j + 1 + x[j] = x[i] + y[j] = y[i] + } + } + + nx = j +end + +# FIND_ISOLATED -- Flag peaks which are within separation of a peak +# with a higher peak value. +# +# The peak positions, x, and their ranks, rank, are input. +# The rank array contains the indices of the peak positions in order from +# the highest peak value to the lowest peak value. Starting with +# highest rank (rank[1]) all peaks of lower rank within separation +# are marked by setting their positions to INDEFI. + +procedure find_isolated (x, rank, nx, separation) + +int x[ARB] # Positions of points +int rank[ARB] # Rank of peaks +int nx # Number of peaks +real separation # Minimum allowed separation + +int i, j + +begin + if ((nx == 0) || (separation <= 0.)) + return + + # Eliminate close neighbors. The eliminated + # peaks are marked by setting their positions to INDEFI. + + for (i = 1; i < nx; i = i + 1) { + if (IS_INDEFI (x[rank[i]])) + next + for (j = i + 1; j <= nx; j = j + 1) { + if (IS_INDEFI (x[rank[j]])) + next + if (abs (x[rank[i]] - x[rank[j]]) < separation) + x[rank[j]] = INDEFI + } + } +end + + +# FIND_NMAX -- Select up to the nmax highest ranked peaks. + +procedure find_nmax (x, rank, nx, nmax, peaks, npeaks) + +int x[ARB] # Peak positions +int rank[ARB] # Ranks of peaks +int nx # Number of input / output peaks +int nmax # Max number of peaks to be selected +real peaks[nmax] # Output peak position array +int npeaks # Output number of peaks + +int i + +begin + for (i = 1; (i <= nx) && (npeaks < nmax); i = i + 1) { + if (IS_INDEFI (x[rank[i]])) + next + npeaks = npeaks + 1 + peaks[npeaks] = x[rank[i]] + } +end + + +# COMPARE -- Compare procedure for sort used in FIND_PEAKS. +# Larger values are indexed first. INDEFR values are indexed last. + +int procedure compare (index1, index2) + +# Procedure parameters: +int index1 # Comparison index +int index2 # Comparison index + +pointer y + +common /sort/ y + +begin + # INDEFR points are considered to be smallest possible values. + if (IS_INDEFR (Memr[y - 1 + index1])) + return (1) + else if (IS_INDEFR (Memr[y - 1 + index2])) + return (-1) + else if (Memr[y - 1 + index1] < Memr[y - 1 + index2]) + return (1) + else if (Memr[y - 1 + index1] > Memr[y - 1 + index2]) + return (-1) + else + return (0) +end diff --git a/noao/twodspec/apextract/t_apall.x b/noao/twodspec/apextract/t_apall.x new file mode 100644 index 00000000..415066ba --- /dev/null +++ b/noao/twodspec/apextract/t_apall.x @@ -0,0 +1,576 @@ +include <imhdr.h> +include <error.h> +include <pkg/gtools.h> +include "apertures.h" + +define APFIND 1 +define APRECENTER 2 +define APRESIZE 3 +define APEDIT 4 +define APTRACE 5 +define APSUM 6 +define APNORM 7 +define APSCAT 8 +define APALL 9 +define APFIT 10 +define APFLAT 11 +define APMASK 12 +define APSCRIPT 13 +define APSLITPROC 14 +define APNOISE 15 + + +# APEXTRACT TASK ENTRY POINTS +# +# The entry point for each task selects the operations to be performed +# and initializes the pset to be used for the algorithm parameters. + +procedure t_apfind () +begin + call apall (APFIND) +end + +procedure t_aprecenter () +begin + call apall (APRECENTER) +end + +procedure t_apresize () +begin + call apall (APRESIZE) +end + +procedure t_apedit () +begin + call apall (APEDIT) +end + +procedure t_aptrace () +begin + call apall (APTRACE) +end + +procedure t_apsum () +begin + call apall (APSUM) +end + +procedure t_apnorm () +begin + call apall (APNORM) +end + +procedure t_apscatter () +begin + call apall (APSCAT) +end + +procedure t_apall () +begin + call apall (APALL) +end + +procedure t_apflat () +begin + call apall (APFLAT) +end + +procedure t_apfit () +begin + call apall (APFIT) +end + +procedure t_apmask () +begin + call apall (APMASK) +end + +procedure t_apscript () +begin + call apall (APSCRIPT) +end + +procedure t_apslitproc () +begin + call apall (APSLITPROC) +end + +procedure t_apnoise () +begin + call apall (APNOISE) +end + + +# APALL -- Master aperture definition and extraction procedure. + +procedure apall (ltask) + +int ltask # Logical task + +bool find # Find apertures? +bool recenter # Recenter apertures? +bool resize # Resize apertures? +bool edit # Edit apertures? +bool trace # Trace apertures? +bool extract # Extract apertures? +bool fit # Extract fit? +bool norm # Normalize spectra? +bool flat # Flatten spectra? +bool scat # Subtract scattered light? +bool mask # Aperture mask? +bool noise # Noise calculation? + +int input # List of input spectra +int refs # List of reference spectra +int out # List of output spectra +pointer format # Output format or fit type +int scatout # List of scattered light images +int profs # List of profile spectra +int line # Dispersion line +int nsum # Lines to sum + +pointer aps # Pointer to array of aperture pointers +int naps # Number of apertures + +char nullstr[1] +int i +pointer sp, image, output, reference, profiles, str, str1 + +bool clgetb(), apgetb(), streq(), ap_answer(), apgans(), apgansb() +int imtopenp(), clgeti(), ap_getim(), ap_dbaccess(), strncmp() + +errchk ap_dbacess, ap_dbread, ap_find, ap_recenter, ap_resize, ap_edit +errchk ap_trace, ap_plot, ap_extract, ap_scatter, ap_mask, ap_dbwrite + +data nullstr /0,0/ + +begin + # Allocate memory for the apertures, filenames, and strings. + call smark (sp) + call salloc (image, SZ_FNAME, TY_CHAR) + call salloc (output, SZ_FNAME, TY_CHAR) + call salloc (reference, SZ_FNAME, TY_CHAR) + call salloc (format, SZ_LINE, TY_CHAR) + call salloc (profiles, SZ_FNAME, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (str1, SZ_LINE, TY_CHAR) + + switch (ltask) { + case APALL: + call apopset ("apall1") + case APFIT: + call apopset ("apfit1") + case APFLAT: + call apopset ("apflat1") + case APNORM: + call apopset ("apnorm1") + case APSCRIPT: + call apopset ("apscript") + case APSLITPROC: + call apopset ("apslitproc") + case APNOISE: + call apopset ("apnoise1") + default: + call apopset ("apparams") + } + + input = imtopenp ("input") + refs = imtopenp ("references") + line = clgeti ("line") + nsum = clgeti ("nsum") + out = NULL + profs = NULL + scatout = NULL + + switch (ltask) { + case APSUM, APALL, APFIT, APNORM, APFLAT, APSCAT, + APMASK, APSCRIPT, APSLITPROC: + out = imtopenp ("output") + } + + switch (ltask) { + case APSUM, APALL: + profs = imtopenp ("profiles") + call apgstr ("format", Memc[format], SZ_LINE) + case APFIT: + call clgstr ("fittype", Memc[format], SZ_LINE) + case APNORM: + call strcpy ("normalize", Memc[format], SZ_LINE) + case APFLAT: + call strcpy ("flatten", Memc[format], SZ_LINE) + case APSCAT: + scatout = imtopenp ("scatter") + case APSCRIPT, APSLITPROC: + scatout = imtopenp ("scatter") + profs = imtopenp ("profiles") + call apgstr ("format", Memc[format], SZ_LINE) + case APNOISE: + call strcpy ("noise", Memc[format], SZ_LINE) + } + + trace = false + extract = false + fit = false + norm = false + flat = false + scat = false + mask = false + noise = false + + if (apgetb ("initialize")) { + find = clgetb ("find") + recenter = clgetb ("recenter") + resize = clgetb ("resize") + edit = clgetb ("edit") + + switch (ltask) { + case APTRACE, APSUM, APALL, APFIT, APNORM, + APFLAT, APSCAT, APMASK, APSCRIPT, APSLITPROC, APNOISE: + trace = clgetb ("trace") + } + + switch (ltask) { + case APSUM, APALL: + extract = clgetb ("extract") + case APFIT: + fit = clgetb ("fit") + case APNORM: + norm = clgetb ("normalize") + case APFLAT: + flat = clgetb ("flatten") + case APSCAT: + scat = clgetb ("subtract") + case APMASK: + mask = clgetb ("mask") + case APSCRIPT, APSLITPROC: + extract = clgetb ("extract") + scat = clgetb ("subtract") + if (extract && scat) + call error (1, + "APSCRIPT: Can't combine scattered light and extraction") + case APNOISE: + noise = true + } + + call ap_init (find, recenter, resize, edit, trace, extract, fit, + norm, flat, scat, mask, noise) + } else { + find = apgans ("ansfind") + recenter = apgans ("ansrecenter") + resize = apgans ("ansresize") + edit = apgans ("ansedit") + + switch (ltask) { + case APTRACE, APSUM, APALL, APFIT, APNORM, + APFLAT, APSCAT, APMASK, APSCRIPT, APSLITPROC, APNOISE: + trace = apgans ("anstrace") + } + + switch (ltask) { + case APSUM, APALL: + extract = apgans ("ansextract") + case APFIT: + fit = apgans ("ansfit") + case APNORM: + norm = apgans ("ansnorm") + case APFLAT: + flat = apgans ("ansflat") + case APSCAT: + scat = apgans ("ansscat") + case APMASK: + mask = apgans ("ansmask") + case APSCRIPT, APSLITPROC: + extract = apgans ("ansextract") + scat = apgans ("ansscat") + if (extract && scat) + call error (1, + "APSCRIPT: Can't combine scattered light and extraction") + } + } + + # Initialize the apertures. + naps = 0 + Memc[reference] = EOS + Memc[profiles] = EOS + call malloc (aps, 100, TY_POINTER) + + # Process the apertures from each input image. + while (ap_getim (input, Memc[image], SZ_FNAME) != EOF) { + if (ap_getim (refs, Memc[str], SZ_LINE) != EOF) + call strcpy (Memc[str], Memc[reference], SZ_FNAME) + if (extract || fit || flat || norm || scat || mask) + if (ap_getim (out, Memc[output], SZ_FNAME) == EOF) + Memc[output] = EOS + + # Get apertures. + call appstr ("ansdbwrite1", "no") + if (streq (Memc[reference], nullstr) || + streq (Memc[reference], Memc[image])) { + if (clgetb ("verbose")) + call printf ("Searching aperture database ...\n") + iferr (call ap_dbread (Memc[image], aps, naps)) + ; + } else if (streq (Memc[reference], "OLD")) { + iferr (call ap_dbread (Memc[image], aps, naps)) + next + } else { + if (strncmp (Memc[reference], "NEW", 3) == 0) { + if (ap_dbaccess (Memc[image]) == YES) + next + call strcpy (Memc[reference+3], Memc[reference], SZ_FNAME) + } + if (clgetb ("verbose")) + call printf ("Searching aperture database ...\n") + iferr (call ap_dbread (Memc[reference], aps, naps)) { + call eprintf ( + "WARNING: Reference image (%s) apertures not found\n") + call pargstr (Memc[reference]) + next + } + if (naps > 0) + call appstr ("ansdbwrite1", "yes") + } + call clgstr ("apertures", Memc[str], SZ_LINE) + call ap_select (Memc[str], Memi[aps], naps) + + iferr { + # Find apertures. + if (find && naps == 0) + call ap_find (Memc[image], line, nsum, aps, naps) + + # Recenter apertures. + else if (recenter) + call ap_recenter (Memc[image], line, nsum, Memi[aps], naps, + NO) + + # Resize apertures. + if (resize) + call ap_resize (Memc[image], line, nsum, Memi[aps], naps, + NO) + + # Edit apertures. + if (edit) + call ap_edit (Memc[image], line, nsum, aps, naps) + + # Trace apertures. + if (trace) + call ap_trace (Memc[image], line, Memi[aps], naps, NO) + + # Write database and make aperture plot. + if (apgansb ("ansdbwrite1")) { + call clgstr ("database", Memc[str1], SZ_LINE) + call sprintf (Memc[str], SZ_LINE, + "Write apertures for %s to %s") + call pargstr (Memc[image]) + call pargstr (Memc[str1]) + if (ap_answer ("ansdbwrite", Memc[str])) + call ap_dbwrite (Memc[image], aps, naps) + } + iferr (call ap_dbwrite ("last", aps, naps)) + ; + iferr (call ap_plot (Memc[image], line, nsum, Memi[aps], naps)) + call erract (EA_WARN) + + # Extract 1D spectra but do not extract negative beams + if (extract) { + do i = 1, naps { + if (AP_BEAM(Memi[aps+i-1]) < 0) + AP_SELECT(Memi[aps+i-1]) = NO + } + + if (ap_getim (profs, Memc[str1], SZ_LINE) != EOF) + call strcpy (Memc[str1], Memc[profiles], SZ_FNAME) + call sprintf (Memc[str], SZ_LINE, + "Extract aperture spectra for %s?") + call pargstr (Memc[image]) + if (ap_answer ("ansextract", Memc[str])) { + call sprintf (Memc[str], SZ_LINE, + "Review extracted spectra from %s?") + call pargstr (Memc[image]) + if (ap_answer ("ansreview", Memc[str])) { + call apgstr ("ansreview", Memc[str], SZ_LINE) + call appstr ("ansreview1", Memc[str]) + } else + call appstr ("ansreview1", "NO") + call ap_extract (Memc[image], Memc[output], + Memc[format], Memc[profiles], Memi[aps], naps) + } + } + + # Fit apertures. + if (fit) { + call sprintf (Memc[str], SZ_LINE, + "Fit apertures in %s?") + call pargstr (Memc[image]) + if (ap_answer ("ansfit", Memc[str])) { + call ap_extract (Memc[image], Memc[output], + Memc[format], nullstr, Memi[aps], naps) + } + } + + # Normalize apertures. + if (norm) { + call sprintf (Memc[str], SZ_LINE, + "Normalize apertures in %s?") + call pargstr (Memc[image]) + if (ap_answer ("ansnorm", Memc[str])) { + call sprintf (Memc[str], SZ_LINE, + "Fit spectra from %s interactively?") + call pargstr (Memc[image]) + if (ap_answer ("ansfitspec", Memc[str])) { + call apgstr ("ansfitspec", Memc[str], SZ_LINE) + call appstr ("ansfitspec1", Memc[str]) + } else + call appstr ("ansfitspec1", "NO") + call ap_extract (Memc[image], Memc[output], + Memc[format], nullstr, Memi[aps], naps) + } + } + + # Flatten apertures. + if (flat) { + call sprintf (Memc[str], SZ_LINE, + "Flatten apertures in %s?") + call pargstr (Memc[image]) + if (ap_answer ("ansflat", Memc[str])) { + call sprintf (Memc[str], SZ_LINE, + "Fit spectra from %s interactively?") + call pargstr (Memc[image]) + if (ap_answer ("ansfitspec", Memc[str])) { + call apgstr ("ansfitspec", Memc[str], SZ_LINE) + call appstr ("ansfitspec1", Memc[str]) + } else + call appstr ("ansfitspec1", "NO") + call ap_extract (Memc[image], Memc[output], + Memc[format], nullstr, Memi[aps], naps) + } + } + + # Substract scattered light. + if (scat) { + if (ap_getim (scatout, Memc[str1], SZ_LINE) == EOF) + Memc[str1] = EOS + if (Memc[output] == EOS || + streq (Memc[image], Memc[output])) { + call mktemp ("tmp", Memc[str], SZ_LINE) + call ap_scatter (Memc[image], Memc[str], + Memc[str1], Memi[aps], naps, line) + call imdelete (Memc[image]) + call imrename (Memc[str], Memc[image]) + } else + call ap_scatter (Memc[image], Memc[output], + Memc[str1], Memi[aps], naps, line) + } + + # Make a aperture mask. + if (mask) + call ap_mask (Memc[image], Memc[output], Memi[aps], naps) + + # Fit noise. + if (noise) + call ap_extract (Memc[image], nullstr, + Memc[format], nullstr, Memi[aps], naps) + + } then + call erract (EA_WARN) + + # Free memory. + for (i = 1; i <= naps; i = i + 1) + call ap_free (Memi[aps+i-1]) + naps = 0 + } + + # Free memory and finish up. + call imtclose (input) + call imtclose (refs) + if (out != NULL) + call imtclose (out) + if (profs != NULL) + call imtclose (profs) + if (norm || flat) + call ap_fitfree () + if (scat) { + if (scatout != NULL) + call imtclose (scatout) + call scat_free () + } + call ap_gclose () + call ap_trfree () + call apcpset () + call sfree (sp) +end + + +procedure ap_init (find, recenter, resize, edit, trace, extract, fit, + norm, flat, scat, mask, noise) + +bool find, recenter, resize, edit, trace +bool extract, fit, norm, flat, scat, mask, noise + +pointer sp, str +bool clgetb() + +begin + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + + if (find) + call appans ("ansfind", find, find) + if (recenter) + call appans ("ansrecenter", recenter, recenter) + if (resize) + call appans ("ansresize", resize, resize) + if (edit) + call appans ("ansedit", edit, false) + if (trace) { + call appans ("anstrace", trace, trace) + call appans ("ansfittrace", clgetb ("fittrace"), false) + } + if (extract) { + call appans ("ansextract", extract, extract) + call appans ("ansreview", clgetb ("review"), false) + } + if (fit) { + call appans ("ansfit", fit, fit) + call appstr ("ansreview1", "NO") + } + if (norm) { + call appans ("ansnorm", norm, norm) + call appans ("ansfitspec", clgetb ("fitspec"), false) + call appstr ("ansreview1", "NO") + } + if (flat) { + call appans ("ansflat", flat, flat) + call appans ("ansfitspec", clgetb ("fitspec"), false) + call appstr ("ansreview1", "NO") + } + if (scat) { + call appans ("ansscat", scat, scat) + call appans ("anssmooth", clgetb ("smooth"), clgetb ("smooth")) + call appans ("ansfitscatter", clgetb ("fitscatter"), false) + call appans ("ansfitsmooth", clgetb ("fitsmooth"), false) + } + if (mask) + call appans ("ansmask", mask, mask) + if (noise) + call appstr ("ansreview1", "NO") + + if (extract || fit || norm || flat) { + if (clgetb ("interactive")) + call appstr ("ansclobber", "no") + else + call appstr ("ansclobber", "NO") + } + + call apgstr ("dbwrite", Memc[str], SZ_LINE) + if (clgetb ("interactive")) + call appstr ("ansdbwrite", Memc[str]) + else { + if (Memc[str] == 'y' || Memc[str] == 'Y') + call appstr ("ansdbwrite", "YES") + else + call appstr ("ansdbwrite", "NO") + } + + call sfree (sp) +end diff --git a/noao/twodspec/apextract/x_apextract.x b/noao/twodspec/apextract/x_apextract.x new file mode 100644 index 00000000..47a5fc1a --- /dev/null +++ b/noao/twodspec/apextract/x_apextract.x @@ -0,0 +1,15 @@ +task apall = t_apall, + apedit = t_apedit, + apfind = t_apfind, + apfit = t_apfit, + apflatten = t_apflat, + apmask = t_apmask, + apnormalize = t_apnorm, + aprecenter = t_aprecenter, + apresize = t_apresize, + apscatter = t_apscatter, + apscript = t_apscript, + apslitproc = t_apslitproc, + apnoise = t_apnoise, + apsum = t_apsum, + aptrace = t_aptrace |