1
C @(#)smosub3.for 13.1.1.1 (ESO-DMD) 06/02/98 18:11:31
2
C===========================================================================
3
C Copyright (C) 1995 European Southern Observatory (ESO)
5
C This program is free software; you can redistribute it and/or
6
C modify it under the terms of the GNU General Public License as
7
C published by the Free Software Foundation; either version 2 of
8
C the License, or (at your option) any later version.
10
C This program is distributed in the hope that it will be useful,
11
C but WITHOUT ANY WARRANTY; without even the implied warranty of
12
C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
C GNU General Public License for more details.
15
C You should have received a copy of the GNU General Public
16
C License along with this program; if not, write to the Free
17
C Software Foundation, Inc., 675 Massachusetts Ave, Cambridge,
20
C Correspondence concerning ESO-MIDAS should be addressed as follows:
21
C Internet e-mail: midas@eso.org
22
C Postal address: European Southern Observatory
23
C Data Management Division
24
C Karl-Schwarzschild-Strasse 2
25
C D 85748 Garching bei Muenchen
27
C===========================================================================
29
SUBROUTINE NORMIT(A,NDIM)
35
DOUBLE PRECISION SUM,DR
42
IF (SUM.GT.10.D-20) THEN
53
SUBROUTINE TEMPLB(FLAG,A,B,NPIX,WEITS,RADIUS,CUTS,STAT)
55
C ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
58
C subroutine TEMPLB version 1.50 860610
59
C K. Banse ESO - Garching
62
C template matching, neighbourhood
65
C replace pixels by weighted sum of nw*nw matrix (nw = 2*radius + 1)
68
C filter image by taking the weighted sum W(x,y) of all points in neighbourhood
69
C of x,y with given radius, and replace original value I(x,y) by W(x,y)
72
C call as TEMPLATE(A,B,NPIX,WEITS,RADIUS,STAT)
75
C FLAG: I*4 function flag:
76
C = 1 for Gauss filter
77
C = 2 for digital filter
80
C A: R*4 array input array
81
C B: R*4 array output array
82
C NPIX: I*4 array no. of pixels per line, no. of lines
83
C WEITS: R*4 array weights for NWX*NWY matrix, ordered as
87
C (NWY-1)*NWX+1 ... NWX*NWY
88
C RADIUS: I*4 array radius of template matrix in x,y
91
C CUTS: R*4 array cut values of result frame
92
C STAT: I*4 return status, should be = 0, else problems...
94
C --------------------------------------------------------------------
98
INTEGER FLAG,NPIX(*),RADIUS(*)
99
INTEGER NX,NY,DIAMX,DIAMY,RADYNX
100
INTEGER N,NP,NL,BINDX,STAT
101
INTEGER WINDX,OFFSET,OFF
102
INTEGER NRDXP1,RADXP1,NXRADX,LEFT
104
REAL A(*),B(*),WEITS(*),CUTS(*)
107
DOUBLE PRECISION DTEST
109
C init variables + test size of template
110
BINDX = 1 !index for frame B
113
DIAMX = RADIUS(1) * 2
114
DIAMY = RADIUS(2) * 2
115
IF ((DIAMX.GE.NX).OR.(DIAMY.GE.NY)) THEN !data matrix at least NW
122
RADYNX = RADIUS(2) * NX !all following constants for
123
RADXP1 = RADIUS(1) + 1 !speed reasons...
124
NXRADX = NX - RADIUS(1)
126
LEFT = RADYNX + RADIUS(1) !lower left corner of template matrix
129
C branch according to filter type
130
IF (FLAG.GE.3) GOTO 5000
134
C main loop over inner lines
138
DO 2000, NL=RADIUS(2)+1,NY-RADIUS(2) !step through each line
140
C step through each pixel of data frame
141
C i.e., OFFSET+RADIUS(1)+1 >>> OFF SET+NX-RADIUS(1)
143
DO 1500, NP=OFFSET+RADXP1,OFFSET+NXRADX
144
DTEST = 0.D0 !clear sum
145
WINDX = 1 !index for weight matrix
147
C sum + weigh inner part
148
DO 1000, OFF=NP-LEFT,NP+LEFT,NX !step through lines of window
149
DO 800, N=OFF,OFF+DIAMX
150
DTEST = DTEST + ( A(N) * WEITS(WINDX) )
155
B(BINDX) = DTEST !fill output frame
164
C finally update the cuts
165
CALL CHCUTS(B,BINDX,CUTS)
168
C here for min/max filter
170
5000 IF (FLAG.EQ.3) THEN
173
DO 7000, NL=RADIUS(2)+1,NY-RADIUS(2) !step through each line
175
C step through each pixel of data frame
176
C i.e., OFFSET+RADIUS(1)+1 >>> OFF SET+NX-RADIUS(1)
178
DO 6000, NP=OFFSET+RADXP1,OFFSET+NXRADX
179
TEST = A(NP-LEFT) !take lower left pixel
181
C find max in inner part
182
DO 5500, OFF=NP-LEFT,NP+LEFT,NX
183
DO 5400, N=OFF,OFF+DIAMX
184
IF (A(N).GT.TEST) TEST = A(N)
188
B(BINDX) = TEST !fill output frame
192
OFFSET = OFFSET + NX !update main offset
198
DO 9000, NL=RADIUS(2)+1,NY-RADIUS(2) !step through each line
200
C step through each pixel of data frame
201
C i.e., OFFSET+RADIUS(1)+1 >>> OFF SET+NX-RADIUS(1)
203
DO 8800, NP=OFFSET+RADXP1,OFFSET+NXRADX
204
TEST = A(NP-LEFT) !take lower left pixel
206
C find min in inner part
207
DO 8600, OFF=NP-LEFT,NP+LEFT,NX
208
DO 8400, N=OFF,OFF+DIAMX
209
IF (A(N).LT.TEST) TEST = A(N)
213
B(BINDX) = TEST !fill output frame
217
OFFSET = OFFSET + NX !update main offset
221
C finally update the cuts
222
CALL CHCUTS(B,BINDX,CUTS)
227
SUBROUTINE CHCUTS(A,ASZ1,CUTS)
236
IF (NDIM.LT.3) RETURN
238
IF (A(1).GT.A(2)) THEN
248
IF (TEST.LT.CUTS(1)) THEN
250
ELSE IF (TEST.GT.CUTS(2)) THEN
258
SUBROUTINE EXPAX(IMNOA,OFFPIX,OUTFR,INBUF,RSTAT)
260
C++++++++++++++++++++++++++++++++++++++++++++++++++
264
C K. Banse ESO - Garching
271
C expand image by duplicating border lines + columns
274
C get the no. of columns to expand at left + at right
275
C get the no. of lines to expand in the beginning + end
276
C flip columns in x, lines in y and add to image
280
C EXPAX(IMNOA,OFFPIX,OUTFR,INBUF,RSTAT)
283
C IMNOA integer file no. of input frame
284
C OFFPIX integer offset for 1. pixel to map
285
C OUTFR char. array output frame
286
C INBUF integer array xl,xr,yb,ye: no. of cols (left/right)
287
C no. of lines (beginning/end)
289
C RSTAT integer return status, 0 = o.k.
294
C--------------------------------------------------
298
INTEGER INBUF(4),RSTAT,OFFPIX
299
INTEGER IAV,N,NN,LOOPLM,RMAIND,CHUNKI,CHUNKO
300
INTEGER NAXISA,MOFF,LOFF,NOLIN
301
INTEGER*8 PNTRX,PNTRY
302
INTEGER IMNOA,IMNOC,IMNOX,IMNOY
303
INTEGER TRUSIZ,SIZE,STAT
304
INTEGER NPIXA(2),NPIXC(2)
305
INTEGER UNI(1),NULO,MADRID(1)
308
CHARACTER CUNITA*64,IDENTA*72
312
DOUBLE PRECISION STEPA(2),STARTA(2)
313
DOUBLE PRECISION STARTC(2)
317
INCLUDE 'MID_INCLUDE:ST_DEF.INC'
319
DATA NPIXA /1,1/, NPIXC /1,1/
320
DATA STARTA /0.0,0.0/, STEPA /1.0,1.0/
321
DATA CUNITA /' '/, IDENTA /' '/
323
INCLUDE 'MID_INCLUDE:ST_DAT.INC'
327
CALL STDRDI(IMNOA,'NAXIS',1,1,IAV,NAXISA,UNI,NULO,STAT)
328
IF (NAXISA.GT.2) NAXISA = 2 !max 2-dim
329
CALL STDRDI(IMNOA,'NPIX',1,NAXISA,IAV,NPIXA,UNI,NULO,STAT)
330
CALL STDRDD(IMNOA,'START',1,NAXISA,IAV,STARTA,UNI,NULO,STAT)
331
CALL STDRDD(IMNOA,'STEP',1,NAXISA,IAV,STEPA,UNI,NULO,STAT)
332
CALL STDRDC(IMNOA,'IDENT',1,1,72,IAV,IDENTA,UNI,NULO,STAT)
334
CALL STDRDC(IMNOA,'CUNIT',1,1,N,IAV,CUNITA,UNI,NULO,STAT)
335
CALL STDRDR(IMNOA,'LHCUTS',1,4,IAV,CUTVAL,UNI,NULO,STAT)
337
C get size of input + output frame
338
SIZE = NPIXA(1) * NPIXA(2)
339
IF ( (INBUF(1).GT.NPIXA(1)) .OR.
340
+ (INBUF(2).GT.NPIXA(1)) .OR.
341
+ (INBUF(1).LT.0) .OR.
342
+ (INBUF(2).LT.0) ) THEN
347
NPIXC(1) = NPIXA(1) + INBUF(1) + INBUF(2)
348
IF (NAXISA.GT.1) THEN
349
IF ( (INBUF(3).GT.NPIXA(2)) .OR.
350
+ (INBUF(4).GT.NPIXA(2)) .OR.
351
+ (INBUF(3).LT.0) .OR.
352
+ (INBUF(4).LT.0) ) THEN
356
NPIXC(2) = NPIXA(2) + INBUF(3) + INBUF(4)
359
C create result frame
360
IF (OFFPIX.LE.0) THEN
361
TRUSIZ = NPIXC(1) * NPIXC(2)
362
CALL STFCRE(OUTFR,D_R4_FORMAT,F_O_MODE,F_IMA_TYPE,
365
CALL STDWRI(IMNOC,'NAXIS',NAXISA,1,1,UNI,STAT)
366
CALL STDWRI(IMNOC,'NPIX',NPIXC,1,NAXISA,UNI,STAT)
367
STARTC(1) = STARTA(1) - (INBUF(1)*STEPA(1))
369
+ STARTC(2) = STARTA(2) - (INBUF(3)*STEPA(2))
370
CALL STDWRD(IMNOC,'START',STARTC,1,NAXISA,UNI,STAT)
371
CALL STDWRD(IMNOC,'STEP',STEPA,1,NAXISA,UNI,STAT)
372
CALL STDWRC(IMNOC,'IDENT',1,IDENTA,1,72,UNI,STAT)
374
CALL STDWRC(IMNOC,'CUNIT',1,CUNITA,1,N,UNI,STAT)
375
CALL STDWRR(IMNOC,'LHCUTS',CUTVAL,1,4,UNI,STAT)
377
CALL STFOPN(OUTFR,D_R4_FORMAT,0,F_IMA_TYPE,IMNOC,STAT)
380
C get buffersize of at least one line but no more than total size
381
NN = 40000 !first guess ...
382
IF (NN.LT.NPIXA(1)) NN = NPIXA(1)
383
IF (NN.GT.SIZE) NN = SIZE
384
NOLIN = NN / NPIXA(1) !buffer = NOLIN * NPIXA(1)
385
CHUNKI = NOLIN * NPIXA(1)
386
CHUNKO = NOLIN * NPIXC(1)
387
IF (NAXISA.GT.1) THEN
388
LOOPLM = NPIXA(2) / NOLIN !get no. of passes through loop
389
RMAIND = NPIXA(2) - (LOOPLM*NOLIN) !and remainder
395
CALL STFCRE('expaxi',D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,
397
CALL STFMAP(IMNOX,F_X_MODE,1,CHUNKI,IAV,PNTRX,STAT)
398
CALL STFCRE('expaxo',D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,
400
CALL STFMAP(IMNOY,F_X_MODE,1,CHUNKO,IAV,PNTRY,STAT)
402
C now we loop through input frame
403
MOFF = 1 + OFFPIX !point to 1. pixel in input fr.
404
IF (NAXISA.GT.1) THEN !point to 1. pixel in output fr.
405
LOFF = (INBUF(3)*NPIXC(1)) + 1
411
CALL STFGET(IMNOA,MOFF,CHUNKI,IAV,MADRID(PNTRX),STAT) !data in
412
CALL EXPA1(MADRID(PNTRX),MADRID(PNTRY),NOLIN,NPIXA(1),
414
CALL STFPUT(IMNOC,LOFF,CHUNKO,MADRID(PNTRY),STAT) !data out
419
IF (RMAIND.GT.0) THEN
420
CHUNKI = RMAIND * NPIXA(1)
421
CHUNKO = RMAIND * NPIXC(1)
422
CALL STFGET(IMNOA,MOFF,CHUNKI,IAV,MADRID(PNTRX),STAT)
423
CALL EXPA1(MADRID(PNTRX),MADRID(PNTRY),RMAIND,NPIXA(1),
425
CALL STFPUT(IMNOC,LOFF,CHUNKO,MADRID(PNTRY),STAT)
428
C for 1-dim frames we are finished
429
CALL STFCLO(IMNOX,STAT)
430
CALL STFCLO(IMNOY,STAT)
431
IF (NAXISA.EQ.1) GOTO 8000
433
C get buffersize of INBUF(3/4)*2 lines
434
IF (INBUF(3).GE.INBUF(4)) THEN
439
IF (NN.EQ.0) GOTO 8000 !nothing to do in Y
441
NN = (2*NN + 1) * NPIXC(1)
442
CALL STFCRE('expaxz',D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,
444
CALL STFMAP(IMNOX,F_X_MODE,1,NN,IAV,PNTRX,STAT)
447
CHUNKI = NN * NPIXC(1)
448
IF (CHUNKI.GT.0) THEN
449
CALL STFGET(IMNOC,1,CHUNKI,IAV,MADRID(PNTRX),STAT)
450
CALL EXPA2(1,MADRID(PNTRX),NPIXC,INBUF(3))
451
CALL STFPUT(IMNOC,1,CHUNKI,MADRID(PNTRX),STAT)
455
CHUNKI = NN * NPIXC(1)
456
IF (CHUNKI.GT.0) THEN
457
MOFF = ((NPIXC(2)-NN)*NPIXC(1)) + 1
458
CALL STFGET(IMNOC,MOFF,CHUNKI,IAV,MADRID(PNTRX),STAT)
459
CALL EXPA2(2,MADRID(PNTRX),NPIXC,INBUF(4))
460
CALL STFPUT(IMNOC,MOFF,CHUNKI,MADRID(PNTRX),STAT)
462
CALL STFCLO(IMNOX,STAT)
464
8000 CALL STFCLO(IMNOC,STAT)
469
SUBROUTINE EXPA1(X,Y,NOLIN,NPIXA,NPIXC,INBUF)
475
INTEGER NOLIN,NPIXA,NPIXC,INBUF(*)
476
INTEGER N,NN,IDX,KDX,IOFF,KOFF
478
C loop over all lines
483
C fill first Y pixels with first flipped X pixels
484
IF (INBUF(1).GT.0) THEN
486
KDX = INBUF(1) + KOFF + 1
487
DO 1000, N=1,INBUF(1)
497
C copy center Y pixels from all X pixels
504
C fill last Y pixels with last flipped X pixels
506
IF (INBUF(2).GT.0) THEN
507
DO 3000, N=1,INBUF(2)
521
SUBROUTINE EXPA2(FLAG,X,NPIXC,INB)
527
INTEGER FLAG,NPIXC(*),INB
528
INTEGER N,NN,IDX,KDX,IOFF,KOFF,MX,MMX
558
SUBROUTINE SORTIT(RA,N,NH,LL)
560
C N = full dimension of RA
561
C NH = index of median - we only sort fully until NH
564
C this is the Heapsort algorithm from "Numerical Recipes", page 231
574
L = LL !that is L = NH/2 + 1
577
10 IF (L.GT.1) THEN !still hiring
580
ELSE !in retirement + promotion phase
581
RRA = RA(IR) !clear a space at end of array
582
RA(IR) = RA(1) !retire the top of the heap into it
583
IR = IR - 1 !decrease the size of the corporation
584
IF (IR.EQ.1) THEN !done with last promotion
585
RA(1) = RRA !the least competent guy of all...
586
GOTO 1000 !now move to insertion part
591
I = L !in hiring as well as in promotion phase
592
J = L + L !we here set up to sift down RRA to its right level
594
20 IF (J.LE.IR) THEN !"Do while J<=IR"
596
IF (RA(J).LT.RA(J+1)) J = J + 1 !compare to the better underling
598
IF (RRA.LT.RA(J)) THEN !demote RRA
608
RA(I) = RRA !put RRA into its slot
614
IF (RA(L).LT.RA(NH)) THEN
619
1010 JM = (JU+JL) / 2
620
IF (RRA.LT.RA(JM)) THEN
625
IF ((JU-JL).GT.1) GOTO 1010 !loop
627
CC DO 1100 M=L,JL+2,-1 !RA kept intact
628
DO 1100 M=NH,JL+2,-1 !ojo - RA not kept intact that way!
629
RA(M) = RA(M-1) !but faster
638
SUBROUTINE XSORT1(RA,NDIM,NH,RINDX)
640
C RA = real array of which the elements were used for sorting INDARR
641
C NDIM = full dimension of RA
642
C NH = index of median - we only sort fully until NH
645
C this is the Heapsort algorithm from "Numerical Recipes", page 233
649
PARAMETER (IXXSIZ = 25000)
651
INTEGER NDIM,NH,RINDX
655
INTEGER INDARR(IXXSIZ),BACKAR(IXXSIZ),SAVARR(IXXSIZ)
656
COMMON /TMPARR/ INDARR,BACKAR,SAVARR
667
10 IF (L.GT.1) THEN !still hiring
671
ELSE !in retirement + promotion phase
673
RRA = RA(INDXT) !clear a space at end of array
674
INDARR(IR) = INDARR(1) !retire the top of the heap into it
675
IR = IR - 1 !decrease the size of the corporation
676
IF (IR.EQ.1) THEN !done with last promotion
677
INDARR(1) = INDXT !the least competent guy of all...
682
I = L !in hiring as well as in promotion phase
683
J = L + L !we here set up to sift down RRA to its right level
685
20 IF (J.LE.IR) THEN !"Do while J<=IR"
687
IF (RA(INDARR(J)).LT.RA(INDARR(J+1)))
688
+ J = J + 1 !compare to the better underling
690
IF (RRA.LT.RA(INDARR(J))) THEN !demote RRA
691
INDARR(I) = INDARR(J)
700
INDARR(I) = INDXT !put RRA into its slot
703
1000 DO 4000, J=1,NDIM !set up the back index array
704
BACKAR(INDARR(J)) = J
712
SUBROUTINE XSORT2(RA,NDIM,NH,JWOFF,NEWRA,XSIZE,NCOUNT,RINDX)
714
C RA = real array of which the elements were used for sorting INDARR
715
C NDIM = full dimension of RA
716
C NH = index of median - we only sorted fully until NH then we inserted
717
C IOFF = index of RA element in question
718
C INDARR = semi sorted index array from last sorting of RA
723
PARAMETER (IXXSIZ = 25000)
725
INTEGER NDIM,NH,JWOFF,XSIZE,NCOUNT,RINDX
726
INTEGER IOFF,INDXT,JL,JU,JM,M,N
728
INTEGER INDARR(IXXSIZ),BACKAR(IXXSIZ),SAVARR(IXXSIZ)
729
COMMON /TMPARR/ INDARR,BACKAR,SAVARR
731
REAL RA(NDIM),NEWRA(NCOUNT)
739
RA(IOFF) = NEWR !new value
743
IF (NEWR.LE.RA(INDARR(2))) !it stays very first
746
IF (NEWR.LE.RA(INDARR(1))) THEN !it's very first
747
DO 1000, M=INDXT,2,-1 !remove old entry
748
INDARR(M) = INDARR(M-1) !by shifting up
749
BACKAR(INDARR(M)) = M
757
IF (INDXT.EQ.NDIM) THEN
758
IF (NEWR.GE.RA(INDARR(NDIM-1))) !it stays very last
761
IF (NEWR.GE.RA(INDARR(NDIM))) THEN !it very last
762
DO 2000, M=INDXT,NDIM-1 !remove old entry
763
INDARR(M) = INDARR(M+1) !by shifting down
764
BACKAR(INDARR(M)) = M
773
QR = NEWR - 1.0 !so we satisy following test
775
QR = RA(INDARR(INDXT-1))
778
IF (NEWR.GT.QR) THEN !INDXT = 1 also done here...
779
IF (NEWR.LE.RA(INDARR(INDXT+1))) GOTO 4900
783
2010 JM = (JU+JL) / 2
784
IF (NEWR.LT.RA(INDARR(JM))) THEN
789
IF ((JU-JL).GT.1) GOTO 2010 !loop
791
DO 2100, M=INDXT,JL-1
792
INDARR(M) = INDARR(M+1)
793
BACKAR(INDARR(M)) = M
798
ELSE IF (NEWR.LT.QR) THEN
802
3010 JM = (JU+JL) / 2
803
IF (NEWR.LT.RA(INDARR(JM))) THEN
808
IF ((JU-JL).GT.1) GOTO 3010 !loop
810
DO 3100, M=INDXT,JL+2,-1
811
INDARR(M) = INDARR(M-1)
812
BACKAR(INDARR(M)) = M
815
BACKAR(IOFF) = JL + 1
818
4900 IOFF = IOFF + XSIZE
826
SUBROUTINE XSAVX(DIRFLG,NDIM)
831
PARAMETER (IXXSIZ = 25000)
833
INTEGER INDARR(IXXSIZ),BACKAR(IXXSIZ),SAVARR(IXXSIZ)
834
COMMON /TMPARR/ INDARR,BACKAR,SAVARR
836
IF (DIRFLG.EQ.1) THEN
847
DO 600, N=1,NDIM !rebuild back index array
848
BACKAR(INDARR(N)) = N