/*+++++++++++++++++++++++++ .IDENTifer SCIA_LV1C_RD_MDS .PURPOSE read SCIAMACHY level 1c MDS .INPUT/OUTPUT call as nr_mds = SCIA_LV1C_RD_MDS( fd, clus_mask, state, &mds ); input: FILE *fd : (open) stream pointer ulong64 clus_mask : mask for cluster selection in/output: struct state1_scia *state : structure with States of the product output: struct mds1c_scia **mds : structure for level 1c MDS .RETURNS number of level 1c MDS read (unsigned int), error status passed by global variable ``nadc_stat'' .COMMENTS This routine allocates memory for the following variables: pixel_ids, pixel_wv, pixel_wv_err, pixel_val, pixel_err, geoN/geoL/geoC -------------------------*/ unsigned int SCIA_LV1C_RD_MDS( FILE *fd, unsigned long long clus_mask, struct state1_scia *state, struct mds1c_scia **mds_out ) /*@globals source;@*/ /*@modifies source@*/ { register unsigned short nc, ncc, ni, nobs; register unsigned int nr_mds = 0u; register unsigned short bcp_in_limb, bcp_deep_space; char *mds_char, *mds_pntr; size_t dsr_length_left, nr_byte; unsigned short ubuff; unsigned short num_clus_file, num_clus_out; struct mds1c_scia *mds = NULL; static unsigned short bcp_in_nadir = 0; const unsigned char uchar_one = 1; const size_t DSR_Read = sizeof(struct mjd_envi) + ENVI_UINT; /* * set variable source (= type of MDS) */ source = (int) state->type_mds; /* * count number of cluster to be read */ num_clus_out = 0; num_clus_file = state->num_clus; for ( nc = 0; nc < num_clus_file; nc++ ) { if ( Get_Bit_LL( clus_mask, state->Clcon[nc].id - uchar_one ) == 1ULL ) num_clus_out++; } /* * check dimension of the output array mds_out */ if ( num_clus_out == 0u || mds_out == NULL ) { if ( mds_out != NULL ) *mds_out = NULL; return 0u; } /* * allocate memory to store output records */ mds = (struct mds1c_scia *) malloc( num_clus_out * sizeof(struct mds1c_scia)); if ( mds == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "mds1_scia" ); *mds_out = mds; /* * initialize MDS-structure */ nc = 0; do { mds[nc].num_obs = 0; mds[nc].num_pixels = 0; mds[nc].pixel_ids = NULL; mds[nc].pixel_wv = NULL; mds[nc].pixel_wv_err = NULL; mds[nc].pixel_val = NULL; mds[nc].pixel_err = NULL; mds[nc].geoN = NULL; mds[nc].geoL = NULL; mds[nc].geoC = NULL; } while ( ++nc < num_clus_out ); /* * rewind/read input data file */ (void) fseek( fd, (long) state->offset, SEEK_SET ); /* * read data set records */ nc = 0; do { mds->type_mds = state->type_mds; mds->state_index = (unsigned char) state->indx; mds->dur_scan = state->dur_scan; /* 1 */ if ( fread( &mds->mjd, sizeof( struct mjd_envi ), 1, fd ) != 1 ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "" ); /* 2 */ if ( fread( &mds->dsr_length, ENVI_UINT, 1, fd ) != 1 ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "" ); #ifdef _SWAP_TO_LITTLE_ENDIAN mds->dsr_length = byte_swap_u32( mds->dsr_length ); #endif /* * now we know the size of this dsr, so read it in memory! */ dsr_length_left = mds->dsr_length - DSR_Read; mds_char = (char *) malloc( dsr_length_left ); if ( mds_char == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "mds_char" ); if ( fread( mds_char, dsr_length_left, 1, fd ) != 1 ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "" ); /* 3 */ (void) memcpy( &mds->quality_flag, mds_char, ENVI_CHAR ); mds_pntr = mds_char + ENVI_CHAR; /* 4 */ (void) memcpy( &mds->orbit_phase, mds_pntr, ENVI_FLOAT ); mds_pntr += ENVI_FLOAT; /* 5 */ (void) memcpy( &ubuff, mds_pntr, ENVI_USHRT ); mds_pntr += ENVI_USHRT; #ifdef _SWAP_TO_LITTLE_ENDIAN ubuff = byte_swap_u16( ubuff ); #endif mds->category = (unsigned char) ubuff; /* 6 */ (void) memcpy( &ubuff, mds_pntr, ENVI_USHRT ); mds_pntr += ENVI_USHRT; #ifdef _SWAP_TO_LITTLE_ENDIAN ubuff = byte_swap_u16( ubuff ); #endif mds->state_id = (unsigned char) ubuff; /* 7 */ (void) memcpy( &ubuff, mds_pntr, ENVI_USHRT ); mds_pntr += ENVI_USHRT; #ifdef _SWAP_TO_LITTLE_ENDIAN ubuff = byte_swap_u16( ubuff ); #endif mds->clus_id = (unsigned char) ubuff; for ( ncc = 0; ncc < state->num_clus; ncc++ ) if ( state->Clcon[ncc].id == mds->clus_id ) break; mds->chan_id = state->Clcon[ncc].channel; mds->coaddf = (unsigned char) state->Clcon[ncc].coaddf; mds->pet = state->Clcon[ncc].pet; if ( Get_Bit_LL(clus_mask,(unsigned char)(mds->clus_id-1)) != 0ULL ){ /* 8 */ (void) memcpy( &mds->num_obs, mds_pntr, ENVI_USHRT ); mds_pntr += ENVI_USHRT; #ifdef _SWAP_TO_LITTLE_ENDIAN mds->num_obs = byte_swap_u16( mds->num_obs ); #endif /* 9 */ (void) memcpy( &mds->num_pixels, mds_pntr, ENVI_USHRT ); mds_pntr += ENVI_USHRT; #ifdef _SWAP_TO_LITTLE_ENDIAN mds->num_pixels = byte_swap_u16( mds->num_pixels ); #endif /* 10 */ (void) memcpy( &mds->rad_units_flag, mds_pntr, ENVI_CHAR ); mds_pntr += ENVI_CHAR; /* 11 */ nr_byte = mds->num_pixels * ENVI_USHRT; mds->pixel_ids = (unsigned short *) malloc( nr_byte ); if ( mds->pixel_ids == NULL ) { free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, "pixel_ids" ); } (void) memcpy( mds->pixel_ids, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* 12 */ nr_byte = mds->num_pixels * ENVI_FLOAT; mds->pixel_wv = (float *) malloc( nr_byte ); if ( mds->pixel_wv == NULL ) { free( mds_char ); NADC_GOTO_ERROR(NADC_ERR_ALLOC, "pixel_wv"); } (void) memcpy( mds->pixel_wv, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* 13 */ mds->pixel_wv_err = (float *) malloc( nr_byte ); if ( mds->pixel_wv_err == NULL ) { free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, "pixel_wv_err" ); } (void) memcpy( mds->pixel_wv_err, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* 14 */ nr_byte = mds->num_obs * mds->num_pixels * ENVI_FLOAT; mds->pixel_val = (float *) malloc( nr_byte ); if ( mds->pixel_val == NULL ) { free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, "pixel_val" ); } (void) memcpy( mds->pixel_val, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* 15 */ mds->pixel_err = (float *) malloc( nr_byte ); if ( mds->pixel_err == NULL ) { free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, "pixel_err" ); } (void) memcpy( mds->pixel_err, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* 16 */ switch ( source ) { case SCIA_NADIR: mds->geoN = (struct geoN_scia *) malloc( mds->num_obs * sizeof( struct geoN_scia )); if ( mds->geoN == NULL ) { free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, "geoN" ); } mds_pntr += SCIA_LV1_RD_GeoN( mds_pntr, mds->num_obs, mds->geoN ); /* * set Rainbow/Sun glint flags and pixel type: 0 (= backscan) else 1 */ for ( nobs = 0; nobs < mds->num_obs; nobs++ ) { mds->geoN[nobs].glint_flag = 0; bcp_in_nadir += state->Clcon[ncc].intg_time; if ( bcp_in_nadir > 64 ) { mds->geoN[nobs].pixel_type = BACK_SCAN; if ( bcp_in_nadir == 80 ) bcp_in_nadir = 0; } else mds->geoN[nobs].pixel_type = FORWARD_SCAN; } break; case SCIA_LIMB: mds->geoL = (struct geoL_scia *) malloc( mds->num_obs * sizeof( struct geoL_scia )); if ( mds->geoL == NULL ) { free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, "geoL" ); } mds_pntr += SCIA_LV1_RD_GeoL( mds_pntr, mds->num_obs, mds->geoL ); /* * set Rainbow/Sun glint flags and pixel type */ bcp_in_limb = 0; bcp_deep_space = mds->num_obs * state->Clcon[ncc].intg_time - 24; for ( nobs = 0; nobs < mds->num_obs; nobs++ ) { mds->geoL[nobs].glint_flag = 0; mds->geoL[nobs].pixel_type = ALONG_TANG_HGHT; if ( nobs == mds->num_obs-1 || bcp_in_limb > bcp_deep_space ) mds->geoL[nobs].pixel_type = DEEP_SPACE; else if ( (bcp_in_limb % 24) == 0 ) mds->geoL[nobs].pixel_type = NEW_TANG_HGHT; bcp_in_limb += state->Clcon[ncc].intg_time; } break; case SCIA_OCCULT: mds->geoL = (struct geoL_scia *) malloc( mds->num_obs * sizeof( struct geoL_scia )); if ( mds->geoL == NULL ) { free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, "geoL" ); } mds_pntr += SCIA_LV1_RD_GeoL( mds_pntr, mds->num_obs, mds->geoL ); /* * set Rainbow/Sun glint flags and pixel type */ for ( nobs = 0; nobs < mds->num_obs; nobs++ ) { mds->geoL[nobs].glint_flag = 0; mds->geoL[nobs].pixel_type = ALONG_TANG_HGHT; } break; case SCIA_MONITOR: mds->geoC = (struct geoC_scia *) malloc( mds->num_obs * sizeof( struct geoC_scia )); if ( mds->geoC == NULL ) { free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, "geoC" ); } mds_pntr += SCIA_LV1_RD_GeoC( mds_pntr, mds->num_obs, mds->geoC ); break; } /* * check if we read the whole DSR */ if ( (size_t)(mds_pntr - mds_char) != dsr_length_left ) { const char *dsd_names[] = { "UNKNOWN", "NADIR", "LIMB", "OCCULTATION", "MONITORING" }; free( mds_char ); NADC_GOTO_ERROR( NADC_ERR_PDS_SIZE, dsd_names[source] ); } /* * byte swap data to local representation */ #ifdef _SWAP_TO_LITTLE_ENDIAN Sun2Intel_L1C_MDS( mds ); #endif if ( ++nr_mds == num_clus_out ) { free( mds_char ); break; } /* * pixel_ids has a value in the range [0..8191] */ for ( ni = 0; ni < mds->num_pixels; ni++ ) mds->pixel_ids[ni] += (mds->chan_id - 1) * CHANNEL_SIZE; mds++; } free( mds_char ); } while ( ++nc < num_clus_file ); /* * update state-record to reflect the actual clusters to be read * note that the dimension of 'mds_out' equals 'num_clus_out' */ num_clus_out = 0; for ( nc = 0; nc < num_clus_file; nc++ ) { if ( Get_Bit_LL( clus_mask, state->Clcon[nc].id - uchar_one ) == 1ULL ) { if ( num_clus_out < nc ) (void) memmove( &state->Clcon[num_clus_out], &state->Clcon[nc], sizeof( struct Clcon_scia ) ); num_clus_out++; } } state->num_clus = num_clus_out; /* * set return values */ return nr_mds; done: *mds_out = NULL; if ( (mds -= nr_mds) != NULL ) SCIA_LV1C_FREE_MDS( source, nr_mds, mds ); return 0u; }
/*+++++++++++++++++++++++++ .IDENTifer SCIA_LV1_RD_ONE_MDS .PURPOSE General function to read one Measurement Data Set .INPUT/OUTPUT call as SCIA_LV1_RD_ONE_MDS( fd, clus_mask, state, mds ); input: FILE *fd : (open) stream pointer ulong64 clus_mask : mask for cluster selection in/output: struct state1_scia *state : structure with States of the product output: struct mds1_scia **mds : structure for level 1b MDS .RETURNS exits on failure .COMMENTS static function -------------------------*/ static void SCIA_LV1_RD_ONE_MDS( FILE *fd, unsigned long long clus_mask, const struct state1_scia *state, /*@partial@*/ struct mds1_scia *mds ) /*@globals errno, nadc_stat, nadc_err_stack, source;@*/ /*@modifies errno, nadc_stat, nadc_err_stack, fd, mds@*/ { register char *mds_pntr; register unsigned short na, nc, ncc, ni, nr; char *mds_char; char msg[64]; size_t nr_byte; unsigned char *glint_flags; const int intg_per_sec = 16 / state->intg_times[state->num_intg-1]; const unsigned short indx_deep_space = state->num_aux - (state->intg_times[0] / state->intg_times[state->num_intg-1]); /* * allocate memory for the Sun glint/Rainbow flags */ glint_flags = (unsigned char *) malloc( (size_t) mds->n_aux ); if ( glint_flags == NULL ) NADC_RETURN_ERROR( NADC_ERR_ALLOC, "glint_flags" ); /* * allocate memory to temporary store data for output structure */ mds_char = (char *) malloc( (size_t) state->length_dsr ); if ( mds_char == NULL ) { free( glint_flags ); NADC_RETURN_ERROR( NADC_ERR_ALLOC, "mds_char" ); } /* * read all MDS parameters of this state */ if ( fread( mds_char, (size_t) state->length_dsr, 1, fd ) != 1 ) { (void) snprintf( msg, 64, "MDS[%-u]: read failed", state->indx ); NADC_GOTO_ERROR( NADC_ERR_FILE_RD, msg ); } /* * read data buffer to MDS structure */ mds_pntr = mds_char; (void) memcpy( &mds->mjd, mds_pntr, sizeof( struct mjd_envi ) ); mds_pntr += sizeof( struct mjd_envi ); (void) memcpy( &mds->dsr_length, mds_pntr, ENVI_UINT ); mds_pntr += ENVI_UINT; #ifdef _SWAP_TO_LITTLE_ENDIAN mds->dsr_length = byte_swap_u32( mds->dsr_length ); #endif if ( mds->dsr_length != state->length_dsr ) { (void) snprintf( msg, 64, "MDS[%-u]: Size according to State/DSR = %-u/%-u", state->indx, state->length_dsr, mds->dsr_length ); NADC_GOTO_ERROR( NADC_ERR_PDS_SIZE, msg ); } (void) memcpy( &mds->quality_flag, mds_pntr, ENVI_CHAR ); mds_pntr += ENVI_CHAR; /* * read scale factor [SCIENCE_CHANNELS] */ nr_byte = (size_t) SCIENCE_CHANNELS * ENVI_UCHAR; (void) memcpy( mds->scale_factor, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* * read satellite flags */ nr_byte = mds->n_aux * ENVI_UCHAR; if ( (mds->sat_flags = (unsigned char *) malloc( nr_byte )) == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "sat_flags" ); (void) memcpy( mds->sat_flags, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* * read red grass flags */ nr_byte = (size_t) state->num_clus * mds->n_aux; if ( (mds->red_grass = (unsigned char *) malloc( nr_byte )) == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "red_grass" ); (void) memcpy( mds->red_grass, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* * read Sun glint flags */ if ( source != SCIA_MONITOR ) { (void) memcpy( glint_flags, mds_pntr, (size_t) mds->n_aux ); mds_pntr += (size_t) mds->n_aux; } /* * read geolocation */ switch ( source ) { case SCIA_NADIR: mds->geoN = (struct geoN_scia *) malloc( mds->n_aux * sizeof( struct geoN_scia ) ); if ( mds->geoN == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "geoN" ); mds_pntr += SCIA_LV1_RD_GeoN( mds_pntr, mds->n_aux, mds->geoN ); /* set Rainbow/Sun glint flag and pixel type: 0 (= backscan) or 1 */ for ( na = 0; na < mds->n_aux; na++ ) { mds->geoN[na].glint_flag = glint_flags[na]; if ( sec_in_scan == 5 ) sec_in_scan = 0; if ( sec_in_scan == 0 ) mds->geoN[na].pixel_type = BACK_SCAN; else mds->geoN[na].pixel_type = FORWARD_SCAN; if ( (na+1) % intg_per_sec == 0 ) sec_in_scan++; } break; case SCIA_LIMB: mds->geoL = (struct geoL_scia *) malloc( mds->n_aux * sizeof( struct geoL_scia ) ); if ( mds->geoL == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "geoL" ); mds_pntr += SCIA_LV1_RD_GeoL( mds_pntr, mds->n_aux, mds->geoL ); /* set Rainbow/Sun glint flags and pixel type */ for ( na = 0; na < mds->n_aux; na++ ) { mds->geoL[na].glint_flag = glint_flags[na]; mds->geoL[na].pixel_type = ALONG_TANG_HGHT; if ( indx_limb >= indx_deep_space ) mds->geoL[na].pixel_type |= DEEP_SPACE; if ( ++indx_limb >= state->num_aux ) indx_limb = 0; } mds->geoL[0].pixel_type |= NEW_TANG_HGHT; break; case SCIA_OCCULT: mds->geoL = (struct geoL_scia *) malloc( mds->n_aux * sizeof( struct geoL_scia ) ); if ( mds->geoL == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "geoL" ); mds_pntr += SCIA_LV1_RD_GeoL( mds_pntr, mds->n_aux, mds->geoL ); /* set Rainbow/Sun glint flags and pixel type */ for ( na = 0; na < mds->n_aux; na++ ) { mds->geoL[na].glint_flag = glint_flags[na]; mds->geoL[na].pixel_type = ALONG_TANG_HGHT; } break; case SCIA_MONITOR: mds->geoC = (struct geoC_scia *) malloc( mds->n_aux * sizeof( struct geoC_scia ) ); if ( mds->geoC == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "geoC" ); mds_pntr += SCIA_LV1_RD_GeoC( mds_pntr, mds->n_aux, mds->geoC ); break; } /* * level 0 header */ mds->lv0 = (struct lv0_hdr *) malloc( mds->n_aux * sizeof( struct lv0_hdr ) ); if ( mds->lv0 == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "lv0" ); mds_pntr += SCIA_LV1_RD_LV0Hdr( mds_pntr, mds->n_aux, mds->lv0 ); /* * PMD values */ if ( source != SCIA_MONITOR ) { nr_byte = mds->n_pmd * ENVI_FLOAT; mds->int_pmd = (float *) malloc( nr_byte ); if ( mds->int_pmd == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "int_pmd" ); (void) memcpy( mds->int_pmd, mds_pntr, nr_byte ); mds_pntr += nr_byte; /* * Fractional polarisation values */ mds->polV = (struct polV_scia *) malloc( mds->n_pol * sizeof( struct polV_scia ) ); if ( mds->polV == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "mds->polV" ); mds_pntr += SCIA_LV1_RD_PolV( mds_pntr, mds->n_pol, mds->polV ); /* * add integration times */ for ( ncc = ni = 0; ni < state->num_intg; ni++ ) { unsigned short n_pol_intg = state->num_polar[ni] / state->num_dsr; for ( nr = 0; nr < n_pol_intg; nr++ ) mds->polV[ncc + nr].intg_time = state->intg_times[ni]; ncc += n_pol_intg; } } /* * cluster data */ (void) strcpy( msg, "" ); nc = ncc = 0; do { unsigned short num = state->Clcon[nc].length * state->Clcon[nc].n_read; switch ( state->Clcon[nc].type ) { case RSIG: case ESIG: if ( Get_Bit_LL( clus_mask, (unsigned char) nc ) == 0ULL ){ size_t byte_dest = ncc * mds->n_aux; size_t byte_src = (ncc + 1) * mds->n_aux; size_t bytes_to_move = (state->num_clus - ncc - 1) * mds->n_aux; (void) memmove( mds->red_grass + byte_dest, mds->red_grass + byte_src, bytes_to_move ); mds_pntr += num * (2 * ENVI_CHAR + ENVI_USHRT); } else { /* mds->clus[ncc].id = state->Clcon[nc].id; */ mds->clus[ncc].sig = (struct Sig_scia *) malloc( (size_t) num * SCIA_SIG ); if ( mds->clus[ncc].sig == NULL ) { (void) snprintf( msg, 25, "clus[%-hu].sig", nc ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, msg ); } nr = 0; do { (void) memcpy( &mds->clus[ncc].sig[nr].corr, mds_pntr, ENVI_CHAR ); mds_pntr += ENVI_CHAR; (void) memcpy( &mds->clus[ncc].sig[nr].sign, mds_pntr, ENVI_USHRT ); #ifdef _SWAP_TO_LITTLE_ENDIAN mds->clus[ncc].sig[nr].sign = byte_swap_u16( mds->clus[ncc].sig[nr].sign ); #endif mds_pntr += ENVI_USHRT; (void) memcpy( &mds->clus[ncc].sig[nr].stray, mds_pntr, ENVI_CHAR ); mds_pntr += ENVI_CHAR; } while ( ++nr < num ); mds->clus[ncc++].n_sig = num; } break; case RSIGC: case ESIGC: if ( Get_Bit_LL( clus_mask, (unsigned char) nc ) == 0ULL ){ size_t byte_dest = ncc * mds->n_aux; size_t byte_src = (ncc + 1) * mds->n_aux; size_t bytes_to_move = (state->num_clus - ncc - 1) * mds->n_aux; (void) memmove( mds->red_grass + byte_dest, mds->red_grass + byte_src, bytes_to_move ); mds_pntr += num * (ENVI_CHAR + ENVI_UINT); } else { /* mds->clus[ncc].id = state->Clcon[nc].id; */ mds->clus[ncc].sigc = (struct Sigc_scia *) malloc( (size_t) num * SCIA_SIGC ); if ( mds->clus[ncc].sigc == NULL ) { (void) snprintf( msg, 25, "clus[%-hu].sigc", nc ); NADC_GOTO_ERROR( NADC_ERR_ALLOC, msg ); } nr = 0; do { (void) memcpy( &mds->clus[ncc].sigc[nr].det.four_byte, mds_pntr, ENVI_UINT ); #ifdef _SWAP_TO_LITTLE_ENDIAN mds->clus[ncc].sigc[nr].det.four_byte = byte_swap_u32( mds->clus[ncc].sigc[nr].det.four_byte ); #endif mds_pntr += ENVI_UINT; (void) memcpy( &mds->clus[ncc].sigc[nr].stray, mds_pntr, ENVI_CHAR ); mds_pntr += ENVI_CHAR; } while ( ++nr < num ); mds->clus[ncc++].n_sigc = num; } break; default: (void) snprintf( msg, 25, "unknown reticon type: %02hu", (unsigned short) state->Clcon[nc].type ); NADC_GOTO_ERROR( NADC_ERR_FATAL, msg ); } } while ( ++nc < state->num_clus ); mds->n_clus = ncc; /* * check if we read the whole DSR */ if ( (nr_byte = mds_pntr - mds_char) != (size_t) state->length_dsr ) { (void) snprintf( msg, 64, "MDS[%-u]: expected: %6u - read: %6zd", state->indx, state->length_dsr, nr_byte ); NADC_GOTO_ERROR( NADC_ERR_PDS_SIZE, msg ); } /* * deallocate memory */ done: free( glint_flags ); free( mds_char ); return; }
/*+++++++++++++++++++++++++ .IDENTifer SCIA_LV1_RD_MDS .PURPOSE read MDS of one state from a SCIAMACHY level 1b product .INPUT/OUTPUT call as nr_mds = SCIA_LV1_RD_MDS( fd, clus_mask, state, &mds ); input: FILE *fd : (open) stream pointer ulong64 clus_mask : mask for cluster selection in/output: struct state1_scia *state : structure with States of the product output: struct mds1_scia **mds : structure for level 1b MDS records .RETURNS number of level 1b MDS read (unsigned int), error status passed by global variable ``nadc_stat'' .COMMENTS This routine allocates memory for the following variables: sat_flags, red_grass, glint_flags, geoN/geoL/geoC, lvl0_header, int_pmd, polV and depending up on the cluster configuration: clus[].sig, clus[].sigc -------------------------*/ unsigned int SCIA_LV1_RD_MDS( FILE *fd, unsigned long long clus_mask, struct state1_scia *state, struct mds1_scia **mds_out ) /*@globals source;@*/ /*@modifies source@*/ { register unsigned short nc, ncc; register unsigned int nr_mds = 0; unsigned int num_mds = state->num_dsr; struct mds1_scia *mds = NULL; if ( num_mds == 0 || mds_out == NULL ) { if ( mds_out != NULL ) *mds_out = NULL; return 0u; } /* * set variable source (= type of MDS) */ source = (int) state->type_mds; /* * allocate memory to store output records */ mds = (struct mds1_scia *) malloc( num_mds * sizeof(struct mds1_scia)); if ( mds == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "mds1_scia" ); *mds_out = mds; /* * rewind/read input data file */ (void) fseek( fd, (long) state->offset, SEEK_SET ); /* * initialize the MDS record and read MDS data of the selected state */ sec_in_scan = 1; indx_limb = 0; do { mds->type_mds = state->type_mds; mds->state_id = (unsigned char) state->state_id; mds->state_index = (unsigned char) state->indx; mds->n_clus = 0; mds->n_aux = state->num_aux / state->num_dsr; if ( source != SCIA_MONITOR ) { mds->n_pmd = PMD_NUMBER * state->num_pmd / state->num_dsr; mds->n_pol = state->total_polar / state->num_dsr; } else { mds->n_pmd = 0u; mds->n_pol = 0u; } mds->sat_flags = NULL; mds->red_grass = NULL; mds->lv0 = NULL; mds->geoC = NULL; mds->geoL = NULL; mds->geoN = NULL; mds->int_pmd = NULL; mds->polV = NULL; for ( nc = 0; nc < MAX_CLUSTER; nc++ ) { mds->clus[nc].n_sig = 0u; mds->clus[nc].sig = NULL; mds->clus[nc].n_sigc = 0u; mds->clus[nc].sigc = NULL; } SCIA_LV1_RD_ONE_MDS( fd, clus_mask, state, mds ); if ( IS_ERR_STAT_FATAL ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "ONE_MDS" ); /* * byte swap data to local representation */ #ifdef _SWAP_TO_LITTLE_ENDIAN Sun2Intel_L1B_MDS( mds ); #endif } while ( mds++, ++nr_mds < num_mds ); /* * update state-record to reflect the actual cluster stored in the MDS record */ for ( nc = ncc = 0; nc < state->num_clus; nc++ ) { if ( Get_Bit_LL( clus_mask, (unsigned char) nc ) == 1ULL ) { if ( ncc < nc ) (void) memmove( &state->Clcon[ncc], &state->Clcon[nc], sizeof( struct Clcon_scia ) ); ncc++; } } state->num_clus = ncc; /* * set return values */ return nr_mds; done: *mds_out = NULL; if ( (mds -= nr_mds) != NULL ) SCIA_LV1_FREE_MDS( source, nr_mds, mds ); return 0u; }
/*+++++++++++++++++++++++++ Main Program or Function +++++++++++++++*/ unsigned int SCIA_LV1_SELECT_MDS( int source, const struct param_record param, FILE *fp, unsigned int num_dsd, const struct dsd_envi *dsd, struct state1_scia **mds_state ) { register unsigned int ni = 0; register unsigned int num_not = 0; register unsigned int num_select = 0; int mjd2000; unsigned int secnd, mu_sec; unsigned int num_state; unsigned int indx_dsd, *indx_state = NULL; double bgn_jdate = 0.; double end_jdate = 0.; struct lads_scia *lads = NULL; struct state1_scia *state = NULL; const double SecPerDay = 24. * 60. * 60.; const bool Save_Extern_Alloc = Use_Extern_Alloc; /* * initialize output array */ *mds_state = NULL; /* * first check type of selected MDS */ switch ( source ) { case SCIA_NADIR: if ( param.write_nadir != PARAM_SET ) return 0u; indx_dsd = ENVI_GET_DSD_INDEX( num_dsd, dsd, "NADIR" ); if ( IS_ERR_STAT_FATAL ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "NADIR" ); if ( dsd[indx_dsd].num_dsr == 0 ) return 0u; break; case SCIA_LIMB: if ( param.write_limb != PARAM_SET ) return 0u; indx_dsd = ENVI_GET_DSD_INDEX( num_dsd, dsd, "LIMB" ); if ( IS_ERR_STAT_FATAL ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "LIMB" ); if ( dsd[indx_dsd].num_dsr == 0 ) return 0u; break; case SCIA_OCCULT: if ( param.write_occ != PARAM_SET ) return 0u; indx_dsd = ENVI_GET_DSD_INDEX( num_dsd, dsd, "OCCULTATION" ); if ( IS_ERR_STAT_FATAL ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "OCCULTATION" ); if ( dsd[indx_dsd].num_dsr == 0 ) return 0u; break; case SCIA_MONITOR: if ( param.write_moni != PARAM_SET ) return 0u; indx_dsd = ENVI_GET_DSD_INDEX( num_dsd, dsd, "MONITORING" ); if ( IS_ERR_STAT_FATAL ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "MONITORING" ); if ( dsd[indx_dsd].num_dsr == 0 ) return 0u; break; default: NADC_GOTO_ERROR( NADC_ERR_FATAL, "unknown MDS state" ); } /* * initialize begin and end julian date of time window */ if ( param.flag_period == PARAM_SET ) { ASCII_2_MJD( param.bgn_date, &mjd2000, &secnd, &mu_sec ); bgn_jdate = mjd2000 + (secnd + mu_sec / 1e6) / SecPerDay; ASCII_2_MJD( param.end_date, &mjd2000, &secnd, &mu_sec ); end_jdate = mjd2000 + (secnd + mu_sec / 1e6) / SecPerDay; } /* * read State of the Products (ADS) */ Use_Extern_Alloc = FALSE; num_state = SCIA_LV1_RD_STATE( fp, num_dsd, dsd, &state ); Use_Extern_Alloc = Save_Extern_Alloc; if ( IS_ERR_STAT_FATAL ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "STATE" ); /* * read Geolocation of States (LADS) */ Use_Extern_Alloc = FALSE; (void) SCIA_RD_LADS( fp, num_dsd, dsd, &lads ); Use_Extern_Alloc = Save_Extern_Alloc; if ( IS_ERR_STAT_FATAL ) NADC_GOTO_ERROR( NADC_ERR_PDS_RD, "LADS" ); /* * allocate memory to store indices to selected MDS records */ indx_state = (unsigned int *) malloc( num_state * sizeof( unsigned int )); if ( indx_state == NULL ) NADC_GOTO_ERROR( NADC_ERR_ALLOC, "indx_state" ); /* * go through all state-records */ do { if ( (int) state[ni].type_mds == source && state[ni].flag_mds == MDS_ATTACHED ) { if ( param.flag_period == PARAM_SET ) { double mjd_date; mjd_date = state[ni].mjd.days + (state[ni].mjd.secnd + state[ni].mjd.musec / 1e6) / SecPerDay; if ( mjd_date < bgn_jdate ) goto Not_Selected; mjd_date += (state[ni].dur_scan / 16.) / SecPerDay; if ( mjd_date > end_jdate ) goto Not_Selected; } if ( ! IS_SELECTED_CAT( param, state[ni].category ) ) goto Not_Selected; if ( ! IS_SELECTED_STATE( param, state[ni].state_id ) ) goto Not_Selected; if ( param.clus_mask != ~0ULL ) { register unsigned short nc = 0; register bool found = FALSE; do { if ( Get_Bit_LL( param.clus_mask, (unsigned char) nc ) != 0ULL ){ found = TRUE; break; } } while ( ++nc < state[ni].num_clus ); if ( ! found ) goto Not_Selected; } if ( param.chan_mask != BAND_ALL ) { register unsigned short nc = 0; register bool found = FALSE; do { if ( SELECTED_CHANNEL( param.chan_mask, state[ni].Clcon[nc].channel )){ found = TRUE; break; } } while ( ++nc < state[ni].num_clus ); if ( ! found ) goto Not_Selected; } if ( param.flag_geoloc == PARAM_SET ) { if ( ! IS_SELECTED_GEO( param, lads[ni].corner ) ) goto Not_Selected; } indx_state[num_select++] = ni; Not_Selected: num_not++; /* FAKE counter, NOT used! */ } } while ( ++ni < num_state ); /* * copy selected state-records to output array */ SCIA_LV1_EXPORT_NUM_STATE( source, (unsigned short) num_select ); if ( num_select > 0u ) { *mds_state = (struct state1_scia *) malloc( num_select * sizeof( struct state1_scia )); if ( *mds_state == NULL ) { num_select = 0u; NADC_GOTO_ERROR( NADC_ERR_ALLOC, "mds_state" ); } for ( ni = 0; ni < num_select; ni++ ) (void) memcpy( &(*mds_state)[ni], &state[indx_state[ni]], sizeof( struct state1_scia ) ); } done: if ( lads != NULL ) free( lads ); if ( state != NULL ) free( state ); if ( indx_state != NULL ) free( indx_state ); return num_select; }