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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
|
include <error.h>
include <imhdr.h>
include <mach.h>
include <time.h>
include <smw.h>
define MAX_NR_BEAMS 100 # Max number of instrument apertures
define MIN_RANGES 100 # Minimum spectra per beam if not given
# T_BSWITCH -- Beam switch a series of spectra to produce a single
# sky subtracted spectrum.
#
# The spectra may be extinction corrected if not already done.
#
# The summation may include an optional statistical weighting
# based on the total countrate summed over a user definable
# piece of the spectrum. If the countrate is <= 0, the
# spectrum is given zero weight.
#
# The data may be organized as data from the IIDS/IRS are usually
# obtained - where the telescope is beam-switched so that the
# object is first in one aperture while sky is observed in the other,
# and then the process is reversed.
#
# If the instrument offers many apertures, "nebular" mode can be used
# to obtain the same effect. Here all apertures observe the object(s)
# at one time; then the telescope is moved so all apertures are observing
# sky.
#
# Both these methods are considered "idsmode". But if there are a different
# number of sky observations than object, an imbalance exists.
# To account for this possibility, all summations are performed by computing
# an average countrate over all observations. Sky countrates can then be
# subtracted from the object. Later the differential countrate is returned
# to an "equivalent" count by multiplying by the exposure time.
#
# Spectra must be dispersion corrected to employ either
# weighting or extinction correction.
#
# The series of spectra may be accumulated in subsets rather than
# over the entire series by specifying a subset rate. (E.g. for
# IIDS data a subset rate of 4 would produce a summed pair for
# every quadruple.)
# Revisions made for WCS support and change from idsmtn.h structure to shdr.h
# structure. Because this program is an awful mess the changes were made a
# small as possible without altering the structure. (5/1/91, Valdes)
procedure t_bswitch ()
char image[SZ_FNAME,MAX_NR_BEAMS+1]
char rec_numbers[SZ_LINE], title[SZ_LINE,MAX_NR_BEAMS]
char ofile[SZ_FNAME], stat_fil[SZ_FNAME]
int sfd, nrecsx
int i, infile, nrecs, def_beam, start_rec, nimage, sub_rate
int records[300], beam_stat[MAX_NR_BEAMS], ncols[MAX_NR_BEAMS]
bool idsmode, extinct, stat, weight, eof_test
pointer ids[MAX_NR_BEAMS+1]
pointer imnames[MAX_NR_BEAMS] # Hold pointers to pointers of image names
pointer imin, sp, obs
# The following arrays are suffixed by either 'o' for object or 's' for sky
int ico [MAX_NR_BEAMS], ics [MAX_NR_BEAMS] # nr obs in beam
real expo [MAX_NR_BEAMS], exps [MAX_NR_BEAMS] # exposure times
pointer accumo[MAX_NR_BEAMS+1], accums[MAX_NR_BEAMS+1] # beam accumulators
pointer counto[MAX_NR_BEAMS], counts[MAX_NR_BEAMS] # counts in each obs
int clpopni(), clgeti(), get_next_image(), decode_ranges()
int open(), mod()
pointer immap()
bool clgetb(), streq()
begin
call smark (sp)
call aclri (ids, MAX_NR_BEAMS+1)
# Open input filename template
infile = clpopni ("input")
# Get range specification
call clgstr ("records", rec_numbers, SZ_LINE)
if (decode_ranges (rec_numbers, records, 100, nrecs) == ERR)
call error (0, "Bad range specification")
# If no ranges is given, filename expansion will occur, so
# we must will need some indication of the number of spectra.
if (nrecs == MAX_INT)
nrecsx = MIN_RANGES
else
nrecsx = nrecs
# Get root name for new records and starting record number
call clgstr ("output", ofile, SZ_FNAME)
start_rec = clgeti ("start_rec")
# Get filename for statistics
call clgstr ("stats", stat_fil, SZ_FNAME)
# Assume spectra are in quadruples?
idsmode = clgetb ("ids_mode")
# Perform de-extinction?
extinct = clgetb ("extinct")
# Use weighting?
weight = clgetb ("weighting")
# Accumulate by subsets? - A very large number implies no subsetting
sub_rate = clgeti ("subset")
# Open statistics file if any
if (streq (stat_fil, "")) {
sfd = NULL
stat = false
} else {
stat = true
sfd = open (stat_fil, APPEND, TEXT_FILE)
}
# Initialize beam-switch status
obs = NULL
call init_file (extinct, def_beam, ico, ics, beam_stat)
# Begin cycling through all images - accumulate if possible
# by beam number
# Initialize range decoder
call reset_next_image ()
# Set up for subsets
nimage = 0
eof_test = false
repeat {
while (get_next_image (infile, records, nrecs, image[1,def_beam],
SZ_FNAME) != EOF) {
# Attempt to open image with extended header -
iferr (imin = immap (image[1,def_beam], READ_ONLY, 0)) {
call eprintf ("[%s]")
call pargstr (image[1,def_beam])
call error (0, "Image not found or header info not available")
}
# Add in to accumlators
call accum_image (imin, ids, accumo, accums, counto, counts,
ico, ics, expo, exps, image, beam_stat, idsmode, extinct,
weight, nrecsx, ncols, title, imnames, sfd, obs)
call printf ("[%s] added\n")
call pargstr (image[1,def_beam])
call flush (STDOUT)
# Close current image
call imunmap (imin)
# Test for subsets
nimage = nimage + 1
if (mod (nimage, sub_rate) == 0)
go to 10
}
# Get here by running out of data
eof_test = true
# Must be careful not to write out the last sums if subsets are
# in effect because the subset check would already have done so
# We can check because "nimage" will not have been bumped
# if EOF was encountered.
if (mod (nimage, sub_rate) != 0) {
# All data has been summed - generate spectra of the accumlations
10 call wrt_accum (ids, image, title, accumo, accums, ico, ics,
counto, counts, expo, exps, ncols, beam_stat, idsmode, weight,
extinct, ofile, start_rec, sub_rate)
# Generate statistics output for this beam
if (stat)
call wrt_stats (sfd, accumo, accums, ico, ics, counto, counts,
expo, exps, image, beam_stat, title, imnames, weight)
# Clear counters and accumulators
call reset_beams (accumo, accums, expo, exps, ico, ics, beam_stat,
ncols)
}
} until (eof_test)
# Put current record counter back into the parameter file for
# subsequent invocations
call clputi ("next_rec", start_rec)
# Close out inputs, outputs, and space
do i = 1, MAX_NR_BEAMS+1
call shdr_close (ids[i])
if (obs != NULL)
call obsclose (obs)
call clpcls (infile)
call close (sfd)
call sfree (sp)
end
# ACCUM_IMAGE -- Opens current pixel file, loads header elements,
# adds current spectrum to accumulator array(s),
# and updates the accumulator status array.
# If not in IDSMODE, then returns both object and
# sky sums for further consideration.
# IDSMODE requires an equal number of each, object and sky, in
# a sequence of OSSO-OSSO or OSSO-SOOS groups.
procedure accum_image (imin, ids, accumo, accums, counto, counts, ico, ics,
expo, exps, image, beam_stat, idsmode, extinct, weight, nrecs,
ncols, title, imnames, sfd, obs)
pointer imin, ids[ARB]
pointer imnames[ARB] # Saved image names for stat printout
pointer sfd # Statistics file
pointer obs # Observatory
pointer accumo[ARB], accums[ARB] # Object and sky accumlators
pointer counto[ARB], counts[ARB] # counting stats
real expo [ARB], exps [ARB] # total exposure times
int ico [ARB], ics [ARB] # number of observations
char image[SZ_FNAME, MAX_NR_BEAMS+1], title[SZ_LINE,MAX_NR_BEAMS]
char observatory[SZ_FNAME]
int beam_stat[ARB], ncols[ARB]
int dum_beam
bool idsmode, extinct, weight, exflag, newobs, obshead
real latitude
int last_len[MAX_NR_BEAMS], name_nr[MAX_NR_BEAMS]
int ifile, nr_beams, i, j, def_beam, beam_nr
int nwaves, ic, nrecs
real airm, wave1, wave2, wt
pointer wave_tbl, extn_tbl, ipacc, ipc, mw
real clgetr(), obsgetr()
pointer smw_openim()
errchk smw_openim, shdr_open, obsimopen
begin
# Bump image file counter
ifile = ifile + 1
# Load header area
mw = smw_openim (imin)
call shdr_open (imin, mw, 1, 1, INDEFI, SHDATA, ids[def_beam])
call smw_close (MW(ids[def_beam]))
accumo[def_beam] = SY(ids[def_beam])
# Check for proper flags
call flag_chk (ids[def_beam], exflag)
if (ifile == 1) {
# Get region for statistics to operate over -
# Currently only one set of wavelengths is available, but
# at some point, it may be desirable to extend this to
# provide a start and ending wavelength for each aperture
# since an aperture must be considered as an independent
# instrument.
# Insert defaults --> entire spectrum
# Now ask user for start and end - if =0.0, use defaults
wave1 = clgetr ("wave1")
wave2 = clgetr ("wave2")
if (wave1 == 0.0)
wave1 = W0(ids[def_beam])
if (wave2 == 0.0)
wave2 = W0(ids[def_beam]) + (IM_LEN(imin,1)-1) *
WP(ids[def_beam])
}
# Determine beam number and add/sub in pixels
# Remember that IIDS/IRS "beams" are 0-indexed
beam_nr = BEAM(ids[def_beam]) + 1
if (beam_nr > MAX_NR_BEAMS || beam_nr < 1)
call error (0, "Illegal beam number")
# Allocate space for this aperture if not already done
# Space must be allocated for 2 lines of spectra for
# each aperture - Line 1 is used to sum up the most
# recent object-sky spectra to maintain the local
# statistics. Line 2 is used for the net accumulation
# over the entire sequence. The statistics from Line 1
# may be used to weigh the observations as they are
# added into the Line 2 accumulation.
#
# For non-IDSMODE the two lines are used for separate
# object and sky sums
if (IS_INDEFI (beam_stat[beam_nr])) {
beam_stat[beam_nr] = 0
# Allocate space for the accumulators for this beam nr
call salloc (accumo[beam_nr], IM_LEN(imin,1), TY_REAL)
call salloc (accums[beam_nr], IM_LEN(imin,1), TY_REAL)
# Zero object and sky accumulators
call amovkr (0.0, Memr[accumo[beam_nr]], IM_LEN(imin,1))
call amovkr (0.0, Memr[accums[beam_nr]], IM_LEN(imin,1))
# Allocate space for statistics array - For each beam,
# a series of up to 'nrecs' spectra may be read, and we
# want to keep track of the stats (=countrates) for each
# observation. For non-idsmode, need sky rates too.
call salloc (counto[beam_nr], nrecs, TY_REAL)
if (!idsmode)
call salloc (counts[beam_nr], nrecs, TY_REAL)
# Allocate space for the image names
call salloc (imnames[beam_nr], nrecs, TY_INT)
name_nr[beam_nr] = 1
do j = 1, nrecs
call salloc (Memi[imnames[beam_nr]+j-1], SZ_LINE, TY_CHAR)
# Save number of points for checking purposes
last_len[beam_nr] = IM_LEN(imin,1)
ncols[beam_nr] = last_len[beam_nr]
# Initialize exposure time
expo[beam_nr] = 0.0
exps[beam_nr] = 0.0
nr_beams = nr_beams + 1
}
# If this is an object observation, save the image name
if (OFLAG(ids[def_beam]) == 1) {
call strcpy (image[1,def_beam], Memc[Memi[imnames[beam_nr]+
name_nr[beam_nr]-1]], SZ_LINE)
name_nr[beam_nr] = name_nr[beam_nr] + 1
}
# If an object observation, save the header elements --
# NOTE that if we get >1 objects before getting a sky, only
# the last observation header is saved!
# The pixel data will be the sum of all objects until the
# |object-sky| count = 0 -- Thus, beam switching does not
# necessarily accumulate by pairs, but depends on how the
# sequence of observations are presented to the program.
# The following test has been deleted so that headers
# will be saved for sky frames as well. This is necessary
# if BSWITCH is to perform the function of EXTINCTION
# only when sky frames are to be written out as well.
if (OFLAG(ids[def_beam]) == 1 || !idsmode) {
# Save headers - could probably be done faster by AMOV
call shdr_copy (ids[def_beam], ids[beam_nr], NO)
# Fix airmass if necessary
if (extinct && IS_INDEF (AM(ids[beam_nr]))) {
call clgstr ("observatory", observatory, SZ_FNAME)
call obsimopen (obs, imin, observatory, NO, newobs, obshead)
if (newobs) {
call obslog (obs, "BSWITCH", "latitude", STDOUT)
if (sfd != NULL)
call obslog (obs, "BSWITCH", "latitude", sfd)
}
latitude = obsgetr (obs, "latitude")
call get_airm (RA(ids[beam_nr]), DEC(ids[beam_nr]),
HA(ids[beam_nr]), ST(ids[beam_nr]), latitude,
AM(ids[beam_nr]))
}
call strcpy (image[1,def_beam], image[1,beam_nr], SZ_FNAME)
# Save length - Each beam may be independent sizes
ncols[beam_nr] = IM_LEN(imin,1)
# Save title, too for same reason
call strcpy (IM_TITLE(imin), title[1,beam_nr], SZ_LINE)
}
# Verify length
if (last_len[beam_nr] != ncols[beam_nr]) {
call eprintf ("[%s] -- Length not consistent %d\n")
call pargstr (image[1,beam_nr])
call pargi (ncols[beam_nr])
ncols[beam_nr] = min (ncols[beam_nr], last_len[beam_nr])
}
last_len[beam_nr] = ncols[beam_nr]
# Check to see if a pair is obtained - then perform statistics
# and add into global accumulator
if (idsmode) {
# Add spectrum to local accumulation buffer --> Use SKY buffer
# At this point of deriving a sequentially local sum, weighting
# is not used.
call add_spec (Memr[accumo[def_beam]], Memr[accums[beam_nr]],
beam_stat[beam_nr], OFLAG(ids[def_beam]), last_len[beam_nr])
# IDSMODE requires that every 2N observations produce an
# OBJECT-SKY pair
if (mod (ifile, 2*nr_beams) == 0)
# Review all beams in use for non-zero pairings
do i = 1, MAX_NR_BEAMS
if (!IS_INDEFI (beam_stat[i]) && beam_stat[i] != 0)
call error (0, "Spectra are not in quadruples")
# Object and sky exposure times must be equal.
if (OFLAG(ids[def_beam]) == 1) {
expo[beam_nr] = expo[beam_nr] + IT(ids[def_beam])
# Increment number of object observations for this beam
ico[beam_nr] = ico[beam_nr] + 1
}
if (beam_stat[beam_nr] == 0) {
# Add up all counts within a region for statistics of objects
# This must be kept separately for each beam number and for
# each observation
# First convert to counts per second (CPS)
call adivkr (Memr[accums[beam_nr]], IT(ids[def_beam]),
Memr[accums[beam_nr]], last_len[beam_nr])
# Sum CPS in statistics region
call sum_spec (Memr[accums[beam_nr]], wave1, wave2,
W0(ids[def_beam]), WP(ids[def_beam]), Memr[counto[beam_nr]+
ico[beam_nr]-1], last_len[beam_nr])
# De-extinct spectrum
if (extinct && !exflag) {
airm = AM(ids[beam_nr])
call de_ext_spec (Memr[accums[beam_nr]], airm,
W0(ids[def_beam]), WP(ids[def_beam]), Memr[wave_tbl],
Memr[extn_tbl], nwaves, last_len[beam_nr])
}
# Add to global accumulator
# Use weights which are proportional to countrate, if desired
if (weight) {
wt = Memr[counto[beam_nr]+ico[beam_nr]-1]
call amulkr (Memr[accums[beam_nr]], wt,
Memr[accums[beam_nr]], last_len[beam_nr])
}
# And add into global sum
call aaddr (Memr[accums[beam_nr]], Memr[accumo[beam_nr]],
Memr[accumo[beam_nr]], last_len[beam_nr])
}
} else {
# Non IDSMODE -accumulate separate object and sky CPS sums
# Set pointers and update obj-sky parameters
if (OFLAG(ids[def_beam]) == 1) {
beam_stat[beam_nr] = beam_stat[beam_nr] + 1
ipacc = accumo[beam_nr]
ipc = counto[beam_nr]
ico[beam_nr] = ico[beam_nr] + 1
ic = ico[beam_nr]
expo[beam_nr] = expo[beam_nr] + IT(ids[def_beam])
} else {
beam_stat[beam_nr] = beam_stat[beam_nr] - 1
ipacc = accums[beam_nr]
ipc = counts[beam_nr]
ics[beam_nr] = ics[beam_nr] + 1
ic = ics[beam_nr]
exps[beam_nr] = exps[beam_nr] + IT(ids[def_beam])
}
# First convert to counts per second (CPS)
call adivkr (Memr[accumo[def_beam]], IT(ids[def_beam]),
Memr[accumo[def_beam]], last_len[beam_nr])
# Get counting stats
call sum_spec (Memr[accumo[def_beam]], wave1, wave2,
W0(ids[def_beam]), WP(ids[def_beam]), Memr[ipc+ic-1],
last_len[beam_nr])
# De-extinct spectrum
if (extinct && !exflag) {
airm = AM(ids[beam_nr])
call de_ext_spec (Memr[accumo[def_beam]], airm,
W0(ids[def_beam]), WP(ids[def_beam]), Memr[wave_tbl],
Memr[extn_tbl], nwaves, last_len[beam_nr])
}
if (weight) {
wt = Memr[ipc+ic-1]
call amulkr (Memr[accumo[def_beam]], wt, Memr[accumo[def_beam]],
last_len[beam_nr])
}
# Add into appropriate accumulator
call aaddr (Memr[accumo[def_beam]], Memr[ipacc], Memr[ipacc],
last_len[beam_nr])
}
return
# INIT_FILE -- Zero the file initializer, the beam counter, beam stats
# and read the extinction data if necessary
entry init_file (extinct, dum_beam, ico, ics, beam_stat)
ifile = 0
nr_beams = 0
def_beam = MAX_NR_BEAMS + 1
dum_beam = def_beam
do i = 1, MAX_NR_BEAMS {
beam_stat[i] = INDEFI
ico[i] = 0
ics[i] = 0
}
# If extinction required, read in extinction file, and sensitivity file
if (extinct)
call get_extn (wave_tbl, extn_tbl, nwaves)
return
# INIT_NAME -- Reset name index counter for a beam number
entry init_name (dum_beam)
name_nr[dum_beam] = 1
return
end
# ACCUM_OUT -- Checks accumulator flags and writes out a new summed
# image if the count is zero
procedure accum_out (accum, image, ncols, title, root, rec, beam_nr,
bsflag, itm, exflag)
real accum[ARB], itm
char image[SZ_FNAME], title[SZ_LINE], root[SZ_FNAME]
int ncols, rec, beam_nr
int bsflag, exflag
pointer imin, imout, spec
char bs_image[SZ_FNAME]
pointer immap(), impl1r()
begin
# Create new image with user area
# Use ROOT for spectrum name and increment starting record number
call sprintf (bs_image, SZ_FNAME, "%s.%04d")
call pargstr (root)
call pargi (rec)
rec = rec + 1
# Provide user info
call printf ("writing: [%s] %s\n")
call pargstr (bs_image)
call pargstr (title)
call flush (STDOUT)
imin = immap (image, READ_ONLY, 0)
imout = immap (bs_image, NEW_COPY, imin)
# Add standard image header
IM_NDIM(imout) = 1
IM_LEN(imout,1) = ncols
IM_PIXTYPE(imout) = TY_REAL
call strcpy (title, IM_TITLE(imout), SZ_LINE)
# Write out pixels
spec = impl1r (imout)
call amovr (accum, Memr[spec], ncols)
# Update changed parameters
if(bsflag == 1)
call imaddi (imout, "BS-FLAG", bsflag)
call imaddr (imout, "EXPTIME", itm)
call imaddi (imout, "EX-FLAG", exflag)
call imunmap (imin)
call imunmap (imout)
# Store new image name back into image
call strcpy (bs_image, image, SZ_FNAME)
end
# ACCUM_NORM - Normalize weighted rate and convert to counts
procedure accum_norm (accum, nr, counts, exp, ncols, weight)
real accum[ARB], counts[ARB], exp
int nr, ncols
bool weight
real sum_wt
int i
begin
# The accumulation is an array weighted by non-normalized weights
# Normalize to total weight to produce a true weighted average
# and multiply by the total exposure to produce
# an equivalent sum
# Add up all weighting factors
if (weight) {
sum_wt = 0.0
do i = 1, nr
sum_wt = sum_wt + counts[i]
} else
sum_wt = real (nr)
if (sum_wt == 0.0)
sum_wt = 1.0
# Correct for exposure time
sum_wt = exp / sum_wt
call amulkr (accum, sum_wt, accum, ncols)
end
# WRT_ACCUM -- Write out accumulations as spectra
procedure wrt_accum (ids, image, title, accumo, accums, ico, ics,
counto, counts, expo, exps, ncols, beam_stat, idsmode, weight,
extinct, ofile, start_rec, sub_rate)
pointer ids[ARB]
char image[SZ_FNAME,MAX_NR_BEAMS+1], title[SZ_LINE,MAX_NR_BEAMS]
pointer accumo[ARB], accums[ARB]
pointer counto[ARB], counts[ARB]
int ico [ARB], ics [ARB]
real expo [ARB], exps [ARB]
int ncols[ARB]
int beam_stat[ARB]
bool idsmode, weight, extinct
char ofile[SZ_FNAME]
int start_rec, sub_rate, bsflag
int i, nr_beams
real exp_ratio
begin
# First compute number of beams
nr_beams = 0
do i = 1, MAX_NR_BEAMS
if (!IS_INDEFI (beam_stat[i]) && ((ico[i] > 0) || (ics[i] > 0)))
nr_beams = nr_beams + 1
# For all present apertures, write out a spectrum
do i = 1, MAX_NR_BEAMS {
if (!IS_INDEFI (beam_stat[i]) && ((ico[i] > 0) || (ics[i] > 0))) {
if (beam_stat[i] != 0 && idsmode) {
call eprintf ("Non-equal number of obj-sky observations")
call eprintf (" beam: %d - residual: %d\n")
call pargi (i-1)
call pargi (beam_stat[i])
# Reset to 0 and force output
beam_stat[i] = 0
}
# The accumulator has a total CPS using non-normalized
# weights - apply normalization and exposure time to
# generate an equivalent COUNT sum.
call accum_norm (Memr[accumo[i]], ico[i], Memr[counto[i]],
expo[i], ncols[i], weight)
if (!idsmode) {
# Separate object and sky sums require sky info
call accum_norm (Memr[accums[i]], ics[i], Memr[counts[i]],
exps[i], ncols[i], weight)
# Then normalize sky exposure time to that of object
if (exps[i] != 0.0)
exp_ratio = expo[i]/exps[i]
else
exp_ratio = 1.0
# Check that some object observtion was made
# If not, then we only have sky data so multiply by -1
# so that the subsequent subtraction will produce a
# positive sky
if (expo[i] == 0.0)
exp_ratio = -1.0
if (exp_ratio != 1.0)
call amulkr (Memr[accums[i]], exp_ratio,
Memr[accums[i]], ncols[i])
# Finally subtract sky from object equivalent counts
call asubr (Memr[accumo[i]], Memr[accums[i]],
Memr[accumo[i]], ncols[i])
}
# Set header flags
# BS flag is not set if the subset rate equals the
# number of apertures since each record in is copied out
if (sub_rate > nr_beams)
bsflag = 1
else
bsflag = -1
if (OFLAG(ids[i]) == 1)
IT(ids[i]) = expo[i]
else
IT(ids[i]) = exps[i]
if (extinct)
EC(ids[i]) = 0
# And write out spectrum, at last
call accum_out (Memr[accumo[i]], image[1,i],
ncols[i], title[1,i], ofile, start_rec, i,
bsflag, IT(ids[i]), EC(ids[i]))
# Reset name entry counter
call init_name (i)
}
}
end
# RESET_BEAMS -- Zeroes the counters and accumulators for additional
# cases
procedure reset_beams (accumo, accums, expo, exps, ico, ics, beam_stat, ncols)
pointer accumo[ARB], accums[ARB]
real expo [ARB], exps [ARB]
int ico [ARB], ics [ARB]
int beam_stat[ARB], ncols[ARB]
int i
begin
do i = 1, MAX_NR_BEAMS
if (!IS_INDEFI (beam_stat[i])) {
expo[i] = 0.0
exps[i] = 0.0
ico[i] = 0
ics[i] = 0
call amovkr (0.0, Memr[accumo[i]], ncols[i])
call amovkr (0.0, Memr[accums[i]], ncols[i])
}
end
# WRT_STATS -- Write out statistics file
procedure wrt_stats (fd, accumo, accums, ico, ics, counto, counts,
expo, exps, image, beam_stat, title, imnames, weight)
int fd
pointer accumo[ARB], accums[ARB], counto[ARB], counts[ARB]
real expo[ARB], exps[ARB]
int ico[ARB], ics[ARB], beam_stat[ARB]
char image[SZ_FNAME,MAX_NR_BEAMS+1]
char title[ARB]
pointer imnames[ARB]
bool weight
int i, j
real cmaxo, cmaxs
char ctime[SZ_TIME]
long clktime()
begin
# Issue time stamp
call cnvtime (clktime (long(0)), ctime, SZ_TIME)
call fprintf (fd, "%s\n\n")
call pargstr (ctime)
# Issue message if weighted sums in effect
if (weight)
call fprintf (fd, "--> Using weighted averages <--\n\n")
# Cycle over beams
do i = 1, MAX_NR_BEAMS {
if (!IS_INDEFI (beam_stat[i])) {
# Write out Object stats if any
if (ico[i] > 0) {
call fprintf (fd, "Object statistics for beam %d -->[%s]\n")
call pargi (i-1)
call pargstr (image[1,i])
call fprintf (fd, "Title: %s\n")
call pargstr (title)
# Find maximum count value for this beam
cmaxo = Memr[counto[i]]
do j = 1, ico[i]
cmaxo = max (cmaxo, Memr[counto[i]+j-1])
call fprintf (fd,
"Obs Relative CPS Image%12wPeak CPS = %10.3g\n")
call pargr (cmaxo)
if (cmaxo == 0.0)
cmaxo = 1.0
do j = 1, ico[i] {
call fprintf (fd, "%3d %8.2f [%s]\n")
call pargi (j)
call pargr (Memr[counto[i]+j-1] / cmaxo)
call pargstr (Memc[Memi[imnames[i]+j-1]])
}
}
# Write out sky stats if any
if (ics[i] > 0) {
call fprintf (fd, "Sky statistics for beam %d\n")
call pargi (i-1)
cmaxs = Memr[counts[i]]
do j = 1, ics[i]
cmaxs = max (cmaxs, Memr[counts[i]+j-1])
call fprintf (fd, "Obs Relative CPS Peak CPS = %10.3g\n")
call pargr (cmaxs)
if (cmaxs == 0.0)
cmaxs = 1.0
do j = 1, ics[i] {
call fprintf (fd, "%3d %8.2f\n")
call pargi (j)
call pargr (Memr[counts[i]+j-1] / cmaxs)
}
}
call fprintf (fd, "\n\n")
}
}
end
# ADD_SPEC -- Accumulate spectrum into array - either add or subtract
# Returns status = net number of object - sky apectra
# = 0 for equal numbers to indicate further
# processing may take place
procedure add_spec (inspec, accum, stat, flag, len)
real inspec[ARB], accum[ARB]
int stat, flag, len
int i, add_sub
begin
add_sub = 0
# Is this an Object or Sky?
# If flag is neither 0 or 1, spectrum is ignored
if (flag == 0)
add_sub = -1
if (flag == 1)
add_sub = +1
if (add_sub == 0) {
stat = INDEFI
return
}
# Is accumulator to be cleared?
if (IS_INDEFI (stat) || stat == 0) {
call amulkr (inspec, real (add_sub), accum, len)
stat = add_sub
} else {
# Add into accumulator
do i = 1, len
accum[i] = accum[i] + add_sub * inspec[i]
stat = stat + add_sub
}
end
# FLAG_CHK -- Check header flags prior to beam switching
procedure flag_chk (ids, exflag)
pointer ids
bool exflag
int bsflag, imgeti()
begin
# BS requires
# 1. dispersion corrected spectra
# 2. non-beam switched
# 3. may be either extinction corrected or not
if (DC(ids) != DCLINEAR)
call error (0, "Spectrum not dispersion corrected")
iferr (bsflag = imgeti (IM(ids), "BS-FLAG"))
bsflag = -1
if (bsflag == 1)
call error (0, "Spectrum already beam-switched")
if (EC(ids) == ECYES)
exflag = true
else
exflag = false
end
|