/* Name- copyMirsSNDToOutputFile.c Language- C Type- MAIN Version- 1.0 Date- 2/28/2026 Programmer- Mike Pettey (STC) Function- This program extracts data from NUCAPS granules and collocates the data to selected collocations times and locations. */ #include #include #include #include #include #include #include #include #include "uthash.h" #include "mirs_collocator.h" void copyGranuleName(char *granule_name, int out_id, int out_index, int out_var_id); long convertDateAndTimeToEpochTime(int date, int time); void convertEpochTimeToDateAndTime(double epoch_time, int *yr, int *md, int *hr, int *ms); void interpolateProfileLogLinear(int num_before_levels, float *before_pressures, float *before_data, int num_after_levels, float *after_pressures, float *after_data); void interpolateProfileLogLog(int num_before_levels, float *before_pressures, float *before_data, int num_after_levels, float *after_pressures, float *after_data); void interpolateHydrometeorProfile(int num_before_levels, float *before_pressures, float *before_data, int num_after_levels, float *after_pressures, float *after_data); void convertFromLevelsToLayers(int num_before_levels, float *before_pressures, float *before_data, int num_after_levels, float *after_pressures, float *after_data); int copyMirsSNDToOutputFile(struct collocation_data *collocations, int num_collocations, char *file_name, size_t file_size, void* nc_buffer, int out_id) { int num_collocations_copied; int n, i, j, coll, level, in_footprint, scan_line, fov; short year, month, day, hour, minute, second; int yyyymmdd, hhmmss, yyyy, mmdd, hh, mmss; int retval, in_id, in_var_id, out_var_id, out_dim_id; int num_pressure_levels, num_pressure_layers, num_channels, num_qc; int program_version, program_release; long epoch_time; int int_value, int_in_fill, int_out_fill; int *int_array; short short_value, short_in_fill, short_out_fill; short *short_array; float *pressure_levels, *pressure_layers; float float_value, float_in_fill, float_out_fill, scaling_factor; float *float_array; float *drift_pressures, *drift_temps, *drift_wvaps; double double_value, double_in_fill; char *attr_string; size_t dim_length, attr_length; size_t output_index[1]; size_t input_1d_index[1], input_1d_count[1]; size_t input_2d_index[2], input_2d_count[2]; size_t input_3d_index[3], input_3d_count[3]; size_t output_2d_index[2], output_2d_count[2]; size_t output_3d_index[3], output_3d_count[3]; float interpolated_pressures[] = { 0.005, 0.025, 0.055, 0.103, 0.176, 0.280, 0.420, 0.604, 0.837, 1.128, 1.484, 1.910, 2.416, 3.008, 3.696, 4.485, 5.384, 6.401, 7.544, 8.821, 10.238, 11.782, 13.480, 15.378, 17.429, 19.676, 22.127, 24.725, 27.573, 30.624, 33.872, 37.371, 41.119, 45.070, 49.267, 53.767, 58.467, 63.465, 68.765, 74.314, 80.163, 86.312, 92.761, 99.510, 106.559, 113.909, 121.607, 129.657, 138.006, 146.705, 155.755, 165.153, 174.952, 185.102, 195.552, 206.400, 217.650, 229.249, 241.249, 253.599, 266.347, 279.497, 293.046, 306.996, 321.295, 336.044, 351.195, 366.743, 382.693, 399.042, 415.842, 433.042, 450.691, 468.742, 487.191, 506.090, 525.389, 545.089, 565.238, 585.838, 606.838, 628.238, 650.039, 672.288, 694.988, 718.086, 741.637, 765.586, 789.936, 814.735, 839.935, 865.586, 891.635, 918.085, 944.936, 972.184, 1000.000, 1027.987, 1056.486, 1085.384 }; float layer_boundary_pressures[] = { 0.016, 2.152, 3.339, 4.92, 5.877, 6.956, 9.511, 11.0, 16.4, 20.9, 32.2, 43.1, 60.9, 83.2, 103.0, 125.6, 142.3, 160.4, 190.3, 223.4, 272.9, 314.1, 343.6, 407.4, 477.9, 535.2, 617.5, 683.6, 777.7, 878.6, 1100.0 }; float layer_midpoint_pressures[] = { 0.435779, 2.702188, 4.078556, 5.384333, 6.401350, 8.166999, 10.237456, 13.520751, 18.559164, 26.144257, 37.385548, 51.488220, 71.471107, 92.748009, 113.926643, 133.776276, 151.169495, 174.924347, 206.407806, 247.324997, 293.017487, 328.629272, 374.594910, 441.712677, 506.009277, 575.369324, 649.990112, 729.638672, 827.124207, 944.206299 }; float interpolated_data[100]; float layer_avg_data[30]; int num_interpolated_levels = 100; int num_layer_boundaries = 31; int num_layers = 30; num_collocations_copied = 0; // Open the input file retval = nc_open_mem(file_name, NC_NOWRITE, file_size, nc_buffer, &in_id); //printf(" File opened: %d\n", retval); if (retval == NC_NOERR) { // Loop through the collocations for (coll=0; coll 0) && (strcmp(collocations[coll].closest_snd_granule, file_name) == 0)) { num_collocations_copied++; //input_index[1] = collocations[coll].closest_footprint; // printf(" Collocation: %d (%d)\n", coll, num_collocations_copied); // Copy the granule name and footprint retval = nc_inq_varid(out_id, "collocated_snd_granule_name", &out_var_id); copyGranuleName(collocations[coll].closest_snd_granule, out_id, coll, out_var_id); // scan_line = (int)(collocations[coll].closest_footprint / 96); // fov = (int)(collocations[coll].closest_footprint % 96); scan_line = collocations[coll].closest_scanline; fov = collocations[coll].closest_fov; retval = nc_inq_varid(out_id, "collocated_footprint_index", &out_var_id); in_footprint = collocations[coll].closest_footprint; nc_put_var1_int(out_id, out_var_id, output_index, &in_footprint); retval = nc_inq_varid(out_id, "collocated_scanline", &out_var_id); nc_put_var1_int(out_id, out_var_id, output_index, &scan_line); retval = nc_inq_varid(out_id, "collocated_field_of_view", &out_var_id); nc_put_var1_int(out_id, out_var_id, output_index, &fov); // Unpack the dimensions retval = nc_inq_dimid(out_id, "P_Level", &out_dim_id); retval = nc_inq_dimlen(out_id, out_dim_id, &dim_length); num_pressure_levels = (int)dim_length; retval = nc_inq_dimid(out_id, "P_Layer", &out_dim_id); retval = nc_inq_dimlen(out_id, out_dim_id, &dim_length); num_pressure_layers = (int)dim_length; retval = nc_inq_dimid(out_id, "Channel", &out_dim_id); retval = nc_inq_dimlen(out_id, out_dim_id, &dim_length); num_channels = (int)dim_length; retval = nc_inq_dimid(out_id, "Qc_dim", &out_dim_id); retval = nc_inq_dimlen(out_id, out_dim_id, &dim_length); num_qc = (int)dim_length; // Copy the program version and release from the attributes retval = nc_inq_attlen(in_id, NC_GLOBAL, "dap_version", &attr_length); attr_string = (char*)malloc((int)attr_length * sizeof(char)); retval = nc_get_att_text(in_id, NC_GLOBAL, "dap_version", attr_string); if (sscanf(attr_string, "v%dr%d", &program_version, &program_release) != 2) { program_version = -32768; program_release = -32768; } free(attr_string); retval = nc_inq_varid(out_id, "program_version", &out_var_id); retval = nc_put_var1_int(out_id, out_var_id, output_index, &program_version); retval = nc_inq_varid(out_id, "program_release", &out_var_id); retval = nc_put_var1_int(out_id, out_var_id, output_index, &program_release); // Copy the date and time input_1d_index[0] = scan_line; retval = nc_inq_varid(in_id, "ScanTime_year", &in_var_id); retval = nc_get_var1_short(in_id, in_var_id, input_1d_index, &year); retval = nc_inq_varid(in_id, "ScanTime_month", &in_var_id); retval = nc_get_var1_short(in_id, in_var_id, input_1d_index, &month); retval = nc_inq_varid(in_id, "ScanTime_dom", &in_var_id); retval = nc_get_var1_short(in_id, in_var_id, input_1d_index, &day); retval = nc_inq_varid(in_id, "ScanTime_hour", &in_var_id); retval = nc_get_var1_short(in_id, in_var_id, input_1d_index, &hour); retval = nc_inq_varid(in_id, "ScanTime_minute", &in_var_id); retval = nc_get_var1_short(in_id, in_var_id, input_1d_index, &minute); retval = nc_inq_varid(in_id, "ScanTime_second", &in_var_id); retval = nc_get_var1_short(in_id, in_var_id, input_1d_index, &second); yyyymmdd = (year*10000) + (month*100) + day; hhmmss = (hour*10000) + (minute*100) + second; epoch_time = convertDateAndTimeToEpochTime(yyyymmdd, hhmmss); epoch_time = (epoch_time + (int)(fov * 0.02746212)) * 1000; convertEpochTimeToDateAndTime((double)epoch_time, &yyyy, &mmdd, &hh, &mmss); yyyymmdd = (yyyy * 10000) + mmdd; hhmmss = (hh * 10000) + mmss; retval = nc_inq_varid(out_id, "date", &out_var_id); nc_put_var1_int(out_id, out_var_id, output_index, &yyyymmdd); retval = nc_inq_varid(out_id, "time", &out_var_id); nc_put_var1_int(out_id, out_var_id, output_index, &hhmmss); // Copy the latitude and longitude input_2d_index[0] = scan_line; input_2d_index[1] = fov; input_2d_count[0] = 1; input_2d_count[1] = 1; retval = nc_inq_varid(in_id, "Latitude", &in_var_id); retval = nc_get_var1_float(in_id, in_var_id, input_2d_index, &float_value); retval = nc_get_att_float(in_id, in_var_id, "_FillValue", &float_in_fill); if (float_value != float_in_fill) { retval = nc_inq_varid(out_id, "latitude", &out_var_id); retval = nc_put_var1_float(out_id, out_var_id, output_index, &float_value); } retval = nc_inq_varid(in_id, "Longitude", &in_var_id); retval = nc_get_var1_float(in_id, in_var_id, input_2d_index, &float_value); retval = nc_get_att_float(in_id, in_var_id, "_FillValue", &float_in_fill); if (float_value != float_in_fill) { retval = nc_inq_varid(out_id, "longitude", &out_var_id); retval = nc_put_var1_float(out_id, out_var_id, output_index, &float_value); } // Copy the chi square value retval = nc_inq_varid(in_id, "ChiSqr", &in_var_id); retval = nc_get_var1_float(in_id, in_var_id, input_2d_index, &float_value); retval = nc_get_att_float(in_id, in_var_id, "_FillValue", &float_in_fill); if (float_value != float_in_fill) { retval = nc_inq_varid(out_id, "ChiSqr", &out_var_id); retval = nc_put_var1_float(out_id, out_var_id, output_index, &float_value); } // Copy the channel frequencies float_array = (float*)malloc(num_channels * sizeof(float)); retval = nc_inq_varid(in_id, "Freq", &in_var_id); retval = nc_get_var_float(in_id, in_var_id, float_array); retval = nc_get_att_float(in_id, in_var_id, "_FillValue", &float_in_fill); retval = nc_inq_varid(out_id, "Freq", &out_var_id); retval = nc_get_att_float(in_id, in_var_id, "_FillValue", &float_out_fill); for (n=0; n