/* wminmax.c Copyright (c) Kapteyn Laboratorium Groningen 1990 All Rights Reserved. */ #include "stdio.h" #include "string.h" #include "stdlib.h" #include "gipsyc.h" #include "anyout.h" #include "fblank.h" #include "setfblank.h" #include "gds_lock.h" #include "gds_unlock.h" #include "gdsc_grid.h" #include "gdsc_intersect.h" #include "gdsc_ndims.h" #include "gdsc_range.h" #include "gdsc_size.h" #include "gdsd_delete.h" #include "gdsd_find.h" #include "gdsd_wint.h" #include "gdsd_rint.h" #include "gdsd_wreal.h" #include "gdsd_rreal.h" #include "gdsi_read.h" #include "minmax3.h" #define MAXDSCNAMLEN 20 /* maximum length of descriptor names */ #define MAXREADBUFLEN 8192 /* maximum size of dynamic read buffer */ typedef struct { char *dsc; fint len; } dsc_struct; typedef struct { char dsc[MAXDSCNAMLEN]; fint level; } des_struct; static dsc_struct minmax_key[] = { { "DATAMIN ", 8 }, { "DATAMAX ", 8 }, { "NBLANK ", 8 } }; #define MAXMINMAXKEY ( sizeof( minmax_key ) / sizeof( dsc_struct ) ) #if defined(TESTBED) static void test( fchar set, des_struct *des, fint num ) { char *buf; fint device = 3; fint k; fint n; fint naxis; fint nel = 0; fint zero = 0; naxis = gdsc_ndims_c( set, &zero ); buf = calloc( MAXDSCNAMLEN + 1 + 20 * naxis, sizeof( char ) ); anyout_c( &device, tofchar( "Deleted the following descriptors:" ) ); anyout_c( &device, tofchar( "Descriptor Level" ) ); for (k = 0; k < num; k++) { strncpy( buf, des[k].dsc, MAXDSCNAMLEN ); buf[MAXDSCNAMLEN] = 0; for (n = 0; n < naxis; n++) { char s[20]; fint axnum = n + 1; fint cerror = 0; fint grid; grid = gdsc_grid_c( set, &axnum, &des[k].level, &cerror ); if (cerror == -19) { sprintf( s, " ..." ); } else { sprintf( s, "%5d", grid ); } strcat( buf, s ); } anyout_c( &device, tofchar( buf ) ); } free( buf ); } #endif static fint minmaxkey( fchar dsc ) { fint d; fint n = 0; do { d = strncmp( dsc.a, minmax_key[n].dsc, minmax_key[n].len ); } while (d && ++n < MAXMINMAXKEY); if (d) return( 0 ); else return( 1 ); } static fint intersect( fchar set, fint *subsets, fint nsubs, fint level ) { fint n; fint r = 0; for (n = 0; !r && n < nsubs; n++) { fint cerror = 0; if (gdsc_intersect_c( set, &subsets[n], &level, &cerror ) != -1) r = 1; } return( r ); } static void destruct( fchar set, fint *subsets, fint nsubs ) { char buf[MAXDSCNAMLEN]; des_struct *des_buf = NULL; fchar dsc; fint derror = 0; fint des_num = 0; fint level = 0; fint n; fint recno = 0; fint err_i = 0; dsc.a = buf; dsc.l = MAXDSCNAMLEN; gds_lock_c(set, &err_i); level = 0; gdsd_find_c( dsc, set, NULL, &recno, &level ); while (recno && level >= 0) { if (minmaxkey( dsc )) { if (intersect( set, subsets, nsubs, level )) { des_buf = realloc( des_buf, sizeof(des_struct) * ( des_num + 1 ) ); strncpy( des_buf[des_num].dsc, dsc.a, MAXDSCNAMLEN ); des_buf[des_num++].level = level; } } gdsd_find_c( dsc, set, NULL, &recno, &level ); } err_i = 0; gds_unlock_c(set, &err_i); #if defined(TESTBED) test( set, des_buf, des_num ); #endif for (n = 0; n < des_num; n++) { dsc.a = des_buf[n].dsc; dsc.l = MAXDSCNAMLEN; level = des_buf[n].level; gdsd_delete_c( set, dsc, &level, &derror ); } free( des_buf ); } /* #> wminmax.dc2 Subroutine: WMINMAX Purpose: Writes (new) minimum and maximum and number of blanks of subsets in the descriptor file and optionally deletes the MINMAX descriptors at intersecting levels. Category: GDS, HEADER File: wminmax.c Author: K.G. Begeman Use: CALL WMINMAX( SET , Input CHARACTER*(*) SUBSETS , Input INTEGER ARRAY DATAMIN , Input REAL ARRAY DATAMAX , Input REAL ARRAY NBLANK , Input INTEGER ARRAY NSUBS , Input INTEGER CHANGE ) Input INTEGER SET Name of GDS set. SUBSETS Array containing subset coordinate words of the subsets for which the minimum and maximum were determined. DATAMIN Array containing the minimum value in the subsets. DATAMAX Array containing the maximum value in the subsets. NBLANK Array containing the number of blanks in the subsets. NSUBS Number of subsets. CHANGE 0 means that minimum and maximum have not changed, anything else means that minimum and maximum have changed and that the MINMAX descriptors at intersecting levels will be removed by WMINMAX. Notes: 1. The so called MINMAX descriptors are: DATAMIN, DATAMAX and NBLANK. 2. When DATAMIN and/or DATAMAX are undefined (BLANK), then the DATAMIN and DATAMAX descriptors will be removed and only the number of blanks (NBLANK) will be written. Updates: Feb 20, 1990: KGB, Document created. #< Fortran to C interface: @ subroutine wminmax( character, integer, real, real, integer, integer, @ integer ) */ void wminmax_c( fchar set , fint *subsets, float *datamin, float *datamax, fint *nblank , fint *nsubs , fint *change ) { fint ns; /* subset loop counter */ fint subdim; /* dimension of subsets */ if (*change) { /* remove descriptors at intersecting levels */ destruct( set, subsets, *nsubs ); } subdim = gdsc_ndims_c( set, subsets ); if (subdim) { for (ns = 0; ns < *nsubs; ns++) { fint gerror = 0; /* GDS error return code */ if (fblank_c( &datamin[ns] )) { /* minimum is BLANK ? */ gdsd_delete_c( set, tofchar( "DATAMIN" ), &subsets[ns], &gerror ); gerror = 0; } else { /* write DATAMIN to descriptor file at subset level */ gdsd_wreal_c( set, tofchar( "DATAMIN" ), &subsets[ns], &datamin[ns], &gerror ); } if (fblank_c( &datamax[ns] )) { /* maximum is BLANK ? */ gdsd_delete_c( set, tofchar( "DATAMAX" ), &subsets[ns], &gerror ); gerror = 0; } else { /* write DATAMAX to descriptor file at subset level */ gdsd_wreal_c( set, tofchar( "DATAMAX" ), &subsets[ns], &datamax[ns], &gerror ); } gdsd_wint_c( set, tofchar( "NBLANK" ), &subsets[ns], &nblank[ns], &gerror ); } } } /* #> uminmax.dc2 Subroutine: UMINMAX Purpose: Determines and updates the minimum and maximum and the number of blanks in subsets. Category: GDS, HEADER File: wminmax.c Author: K.G. Begeman Use: CALL UMINMAX( SET , Input CHARACTER*(*) SUBSETS , Input INTEGER ARRAY NSUBS , Input INTEGER CHANGE ) Input INTEGER SET Name of GDS set. SUBSETS Array containing subset coordinate words of the subsets for which the minimum and maximum are to be determined. NSUBS Number of subsets. CHANGE 0 means that minimum and maximum have not changed, anything else means that minimum and maximum have changed and that the MINMAX descriptors at intersecting levels will be removed by UMINMAX. Notes: 1. The so called MINMAX descriptors are: DATAMIN, DATAMAX and NBLANK. 2. When no defined DATAMIN and DATAMAX, then BLANK will be returned and the DATAMIN and DATAMAX descriptors will be removed and only the number of blanks (NBLANK) will be written. Updates: Feb 21, 1990: KGB, Document created. #< Fortran to C interface: @ subroutine uminmax( character, integer, integer, integer ) */ void uminmax_c( fchar set , fint *subsets, fint *nsubs , fint *change ) { fint buf_len; fint n_pixels = 1; fint n; fint naxis; fint *nblank; fint ns; fint zero = 0; float *buffer; float *datamin; float *datamax; naxis = gdsc_ndims_c( set, &zero ); for (n = 0; n < naxis; n++) { fint axnum = n + 1; fint cerror = 0; fint grid; grid = gdsc_grid_c( set, &axnum, subsets, &cerror ); if (cerror == -19) { cerror = 0; n_pixels *= gdsc_size_c( set, &axnum, &cerror ); } } if (n_pixels > MAXREADBUFLEN) { buf_len = MAXREADBUFLEN; } else { buf_len = n_pixels; } buffer = calloc( buf_len, sizeof( float ) ); nblank = calloc( *nsubs, sizeof( fint ) ); datamin = calloc( *nsubs, sizeof( float ) ); datamax = calloc( *nsubs, sizeof( float ) ); for (ns = 0; ns < *nsubs; ns++) { fint cerror = 0; fint count = 0; fint cwhi; fint cwlo; fint t_id = 0; gdsc_range_c( set, &subsets[ns], &cwlo, &cwhi, &cerror ); do { fint pixels_done; gdsi_read_c( set, &cwlo, &cwhi, buffer, &buf_len, &pixels_done, &t_id ); minmax3_c( buffer, &pixels_done, &datamin[ns], &datamax[ns], &nblank[ns], &count ); } while (t_id > 0); } wminmax_c( set, subsets, datamin, datamax, nblank, nsubs, change ); free( nblank ); free( datamin ); free( datamax ); } /* #> rminmax.dc2 Subroutine: RMINMAX Purpose: Finds the minimum and maximum and the number of blanks in subsets by reading the corresponding descriptors or, when they are not present, by determining them. Category: GDS, HEADER File: wminmax.c Author: K.G. Begeman Use: CALL RMINMAX( SET , Input CHARACTER*(*) SUBSETS , Input INTEGER ARRAY DATAMIN , Output REAL ARRAY DATAMAX , Output REAL ARRAY NBLANK , Output INTEGER ARRAY NSUBS , Input INTEGER CHANGE ) Input INTEGER SET Name of GDS set. SUBSETS Array containing subset coordinate words of the subsets for which the minimum and maximum are to be determined. DATAMIN Array containing the minimum value in the subsets. DATAMAX Array containing the maximum value in the subsets. NBLANK Array containing the number of blanks in the subsets. NSUBS Number of subsets. CHANGE 0 means that minimum and maximum have not changed, anything else means that minimum and maximum have changed and that the MINMAX descriptors at intersecting levels will be removed by RMINMAX. Notes: 1. The so called MINMAX descriptors are: DATAMIN, DATAMAX and NBLANK. 2. When no defined DATAMIN and DATAMAX, then BLANK will be returned and the DATAMIN and DATAMAX descriptors will be removed and only the number of blanks (NBLANK) will be written. Updates: Feb 20, 1990: KGB, Document created. #< Fortran to C interface: @ subroutine rminmax( character, integer, real, real, integer, integer, @ integer ) */ void rminmax_c( fchar set , fint *subsets, float *datamin, float *datamax, fint *nblank , fint *nsubs , fint *change ) { fint nd = 0; /* number of subsets we still have to work on */ fint ns; /* subset loop counter */ fint *ptrs = NULL; /* pointer to subsets in argument list */ fint subdim; /* dimension of subsets */ fint *subs = NULL; /* list of subsets for which we still have to work on */ if (*change) { /* remove descriptors at intersecting levels */ uminmax_c( set, subsets, nsubs, change ); } subdim = gdsc_ndims_c( set, subsets ); if (subdim) { for (ns = 0; ns < *nsubs; ns++) { fint gerror = 0; /* GDS error return code */ gdsd_rint_c( set, tofchar( "NBLANK" ), &subsets[ns], &nblank[ns], &gerror ); if (gerror != subsets[ns]) { /* we have to determine it ourselves */ gerror = 0; subs = realloc( subs, ( nd + 1 ) * sizeof( fint ) ); ptrs = realloc( ptrs, ( nd + 1 ) * sizeof( fint ) ); subs[nd] = subsets[ns]; ptrs[nd] = ns; nd += 1; } else { gdsd_rreal_c( set, tofchar( "DATAMIN" ), &subsets[ns], &datamin[ns], &gerror ); if (gerror != subsets[ns]) { gerror = 0; setfblank_c( &datamin[ns] ); } gdsd_rreal_c( set, tofchar( "DATAMAX" ), &subsets[ns], &datamax[ns], &gerror ); if (gerror != subsets[ns]) { gerror = 0; setfblank_c( &datamax[ns] ); } } } if (nd) { /* list of subsets we have to work on */ uminmax_c( set, subs, &nd, change ); for (ns = 0; ns < nd; ns++) { fint nq = ptrs[ns]; fint gerror = 0; /* GDS error return code */ gdsd_rint_c( set, tofchar( "NBLANK" ), &subsets[nq], &nblank[nq], &gerror ); gdsd_rreal_c( set, tofchar( "DATAMIN" ), &subsets[nq], &datamin[nq], &gerror ); if (gerror != subsets[nq]) { gerror = 0; setfblank_c( &datamin[nq] ); } gdsd_rreal_c( set, tofchar( "DATAMAX" ), &subsets[nq], &datamax[nq], &gerror ); if (gerror != subsets[nq]) { gerror = 0; setfblank_c( &datamax[nq] ); } } free( subs ); free( ptrs ); } } else { for (ns = 0; ns < *nsubs; ns++) { fint done; fint one = 1; fint tid = 0; gdsi_read_c( set, &subsets[ns], &subsets[ns], &datamin[ns], &one, &done, &tid ); datamax[ns] = datamin[ns]; if (fblank_c( &datamax[ns] )) nblank[ns] = 1; else nblank[ns] = 0; } } }