aboutsummaryrefslogtreecommitdiff
path: root/noao/onedspec/ecidentify/eclinelist.x
blob: 6653dd4b778f63edafca1dff84f37008aadf7113 (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
281
include	<error.h>
include	<mach.h>
include	<smw.h>
include	<units.h>
include	"ecidentify.h"

# EC_MAPLL -- Read the line list into memory.

procedure ec_mapll (ec)

pointer	ec		# Echelle pointer

int	fd, nalloc, nlines, open(), fscan(), nscan()
double	value, lastval
pointer	ec_ll
pointer	sp, str, units, un_open()
bool	streq()
errchk	open, fscan, malloc, realloc, un_open

begin
	EC_LL(ec) = NULL

	call xt_stripwhite (Memc[EC_COORDLIST(ec)])
	if (Memc[EC_COORDLIST(ec)] == EOS)
	    return
	iferr (fd = open (Memc[EC_COORDLIST(ec)], READ_ONLY, TEXT_FILE))
	    return

	call smark (sp)
	call salloc (str, SZ_LINE, TY_CHAR)
	call salloc (units, SZ_LINE, TY_CHAR)
	call strcpy ("Angstroms", Memc[units], SZ_LINE)

	lastval = -MAX_DOUBLE
	nalloc = 0
	nlines = 0
	while (fscan (fd) != EOF) {
	    call gargwrd (Memc[str], SZ_LINE)
	    if (nscan() != 1)
		next
	    if (Memc[str] == '#') {
		call gargwrd (Memc[str], SZ_LINE)
		call strlwr (Memc[str])
		if (streq (Memc[str], "units")) {
		    call gargstr (Memc[units], SZ_LINE)
		    call xt_stripwhite (Memc[units])
		}
		next
	    }
	    call reset_scan ()

	    call gargd (value)
	    if (nscan() != 1)
		next

	    if (nalloc == 0) {
		nalloc = 100
		call malloc (ec_ll, nalloc, TY_DOUBLE)
	    } else if (nlines == nalloc) {
		nalloc = nalloc + 100
		call realloc (ec_ll, nalloc, TY_DOUBLE)
	    }

	    if (value < lastval) {
		call close (fd)
		call mfree (ec_ll, TY_DOUBLE)
		call error (0, "Line list not sorted in increasing order")
	    }

	    Memd[ec_ll+nlines] = value
	    nlines = nlines + 1
	}
	call close (fd)

	if (nlines > 0) {
	    call realloc (ec_ll, nlines + 1, TY_DOUBLE)
	    Memd[ec_ll+nlines] = INDEFD
	    EC_LL(ec) = ec_ll

	    if (EC_UN(ec) == NULL && Memc[units] != EOS)
		EC_UN(ec) = un_open (Memc[units])
	    call ec_unitsll (ec, Memc[units])
	}

	call sfree (sp)
end


# EC_UNMAPLL -- Unmap the linelist.

procedure ec_unmapll (ec)

pointer	ec		# Line list pointer

begin
	call mfree (EC_LL(ec), TY_DOUBLE)
end


# EC_UNITSLL -- Change the line list units from the input units to the
# units given by EC_UN.  This may involve reversing the order of the list.

procedure ec_unitsll (ec, units)

pointer	ec			# Identify structure
char	units[ARB]		# Input units

int	i, nll
double	value
pointer	un, ll, llend, un_open()
bool	un_compare()
errchk	un_open

begin
	if (EC_LL(ec) == NULL)
	    return
	if (IS_INDEFD(Memd[EC_LL(ec)]))
	    return
	if (units[1] == EOS || EC_UN(ec) == NULL)
	    return
	if (UN_CLASS(EC_UN(ec)) == UN_UNKNOWN)
	    return

	un = un_open (units)
	if (un_compare (un, EC_UN(ec))) {
	    call un_close (un)
	    return
	}

	ll = EC_LL(ec)
	do i = 0, ARB
	    if (IS_INDEFD(Memd[ll+i])) {
		nll = i
		break
	    }
	call un_ctrand (un, EC_UN(ec), Memd[ll], Memd[ll], nll)
	call un_close (un)

	if (Memd[ll] > Memd[ll+nll-1]) {
	    llend = ll + nll - 1
	    do i = 0, nll / 2 - 1 {
		value = Memd[ll+i]
		Memd[ll+i] = Memd[llend-i]
		Memd[llend-i] = value
	    }
	}
end



# EC_MATCH -- Match current feature against a line list.

procedure ec_match (ec, in, out)

pointer	ec			# Echelle pointer
double	in			# Coordinate to be matched
double	out			# Matched coordinate

double	match, alpha, delta, delta1, delta2, out1
pointer	ll

begin
	if (EC_LL(ec) == NULL) {
	    out = in
	    return
	}

	match = EC_MATCH(ec)
	alpha = 1.25
	delta1 = MAX_REAL

	# Find nearest match.
	for (ll=EC_LL(ec); !IS_INDEFD(Memd[ll]); ll = ll + 1) {
	    delta = abs (in - Memd[ll])
	    if (delta < delta1) {
	        delta2 = delta1
		delta1 = delta
	        if (delta1 <= match)
		    out1 = Memd[ll]
	    }
	}

	# Only return match if no other candidate is also possible.
	if (delta1 > match)
	    return
	if (delta2 < alpha * delta1)
	    return

	out = out1
end

# EC_LINELIST -- Add features from a line list.

procedure ec_linelist (ec)

pointer	ec			# Echelle pointer

int	i, line, ap, nfound, nextpix
double	pix, fit, user, peak, minval, match, fit1, fit2
pointer	sp, aps, pixes, fits, users, peaks, ll

double	ec_center(), ec_fittopix(), ec_fitpt(), ec_peak()

begin
	if (EC_LL(ec) == NULL)
	    return

	call smark (sp)
	call salloc (aps, EC_MAXFEATURES(ec), TY_INT)
	call salloc (pixes, EC_MAXFEATURES(ec), TY_DOUBLE)
	call salloc (fits, EC_MAXFEATURES(ec), TY_DOUBLE)
	call salloc (users, EC_MAXFEATURES(ec), TY_DOUBLE)
	call salloc (peaks, EC_MAXFEATURES(ec), TY_DOUBLE)

	nfound = 0
	minval = MAX_REAL

	do line = 1, EC_NLINES(ec) {
	    call ec_gline (ec, line)
	    ap = APS(ec,line)
	    fit1 = min (FITDATA(ec,1), FITDATA(ec,EC_NPTS(ec)))
	    fit2 = max (FITDATA(ec,1), FITDATA(ec,EC_NPTS(ec)))
	    for (ll=EC_LL(ec); !IS_INDEFD(Memd[ll]); ll = ll + 1) {
	        user = Memd[ll]
	        if (user < fit1)
		    next
	        if (user > fit2)
		    break

	        pix = ec_center (ec, ec_fittopix (ec, user), EC_FWIDTH(ec),
		    EC_FTYPE(ec))
	        if (!IS_INDEFD(pix)) {
		    fit = ec_fitpt (ec, ap, pix)
		    match = abs (fit - user)
		    if (match > EC_MATCH(ec))
		        next
			
		    peak = abs (ec_peak (ec, pix))
		    if (nfound < EC_MAXFEATURES(ec)) {
		        nfound = nfound + 1
		        if (peak < minval) {
		    	    nextpix = nfound
			    minval = peak
		        }
		        Memi[aps+nfound-1] = ap
		        Memd[pixes+nfound-1] = pix
		        Memd[fits+nfound-1] = fit
		        Memd[users+nfound-1] = user
		        Memd[peaks+nfound-1] = peak
		    } else if (peak > minval) {
		        Memi[aps+nextpix-1] = ap
		        Memd[pixes+nextpix-1] = pix
		        Memd[fits+nextpix-1] = fit
		        Memd[users+nextpix-1] = user
		        Memd[peaks+nextpix-1] = peak

		        minval = MAX_REAL
		        do i = 1, nfound {
			    peak = Memd[peaks+i-1]
			    if (peak < minval) {
			        nextpix = i
			        minval = peak
			    }
		        }
		    }
	        }
	    }
	}
	call ec_gline (ec, EC_LINE(ec))

	do i = 1, nfound {
	    ap = Memi[aps+i-1]
	    pix = Memd[pixes+i-1]
	    fit = Memd[fits+i-1]
	    user = Memd[users+i-1]
	    call ec_newfeature (ec, ap, pix, fit, user, EC_FWIDTH(ec),
		EC_FTYPE(ec))
	}

	call sfree (sp)
end