aboutsummaryrefslogtreecommitdiff
path: root/noao/twodspec/apextract/apmw.x
blob: 9fcd35d73b00cfe3dae5bb6713439117f50446cb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
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