16 #include <GeographicLib/Geodesic.hpp>
17 #include <GeographicLib/Constants.hpp>
18 #include <GeographicLib/Rhumb.hpp>
24 using namespace netCDF;
25 using namespace netCDF::exceptions;
26 using namespace GeographicLib;
56 nrec_3D_view =
nullptr;
57 nrec_4D_band =
nullptr;
65 QC_bitwise_4D =
nullptr;
71 obs_per_view =
nullptr;
109 if (binl1c->
time_gd !=
nullptr)
112 if (binl1c->
alt !=
nullptr)
114 binl1c->
alt =
nullptr;
115 if (binl1c->
lat_gd !=
nullptr)
118 if (binl1c->
lon_gd !=
nullptr)
127 if (binl1c->
alt_2D !=
nullptr)
133 if (binl1c->
i_diff2 !=
nullptr)
136 if (binl1c->
suna_3D !=
nullptr)
139 if (binl1c->
sunz_3D !=
nullptr)
142 if (binl1c->
sena_3D !=
nullptr)
145 if (binl1c->
senz_3D !=
nullptr)
148 if (binl1c->
sca_3D !=
nullptr)
154 if (binl1c->
nrec_2D !=
nullptr)
157 if (binl1c->
nrec_3D !=
nullptr)
166 if (binl1c->
I_4D !=
nullptr)
168 binl1c->
I_4D =
nullptr;
178 cout <<
"allocating/init high order dimensional arrays for L1C binning----------------------------"
180 cout <<
"nviews.." << binl1c->
nviews <<
"nbands.." << binl1c->
nbands <<
"#gridlines.."
216 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
218 binl1c->
alt[
i][
j] = 0.;
228 for (
int v = 0;
v < binl1c->
nviews;
v++) {
252 short gd_row = -1, gd_col = -1;
257 for (
int pix = 0; pix <
npix; pix++)
259 gd_row = gdindex[pix][0] - 1;
260 gd_col = gdindex[pix][1] - 1;
262 if (
l1rec->height[pix] != fill_height &&
l1rec->tilt != fill_tilt && gd_row >= 0 && gd_col >= 0 &&
267 binl1c->
alt_diff2[gd_row][gd_col] + (
l1rec->height[pix] - binl1c->
alt[gd_row][gd_col]) *
268 (
l1rec->height[pix] - binl1c->
alt[gd_row][gd_col]);
279 cout <<
"adding alt_rmse to L1C file..." << endl;
281 NcGroup geo_grp = nc_output->getGroup(
"geolocation_data");
282 NcVar v1 = geo_grp.getVar(
"height_stdev");
285 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
300 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
301 for (
int v = 0;
v < binl1c->
nviews;
v++) {
314 NcGroup od_grp = nc_output->getGroup(
"observation_data");
315 v1 = od_grp.getVar(
"i_stdev");
317 v1 = od_grp.getVar(
"i_stdev");
318 v1.putVar(&temp2[0][0][0][0]);
328 cout <<
"adding final binned vars to ...." << binl1c->
full_l1cgrid << endl;
330 NcDim ydim = nc_output->getDim(
"bins_along_track");
331 NcDim xdim = nc_output->getDim(
"bins_across_track");
332 NcDim vdim = nc_output->getDim(
"number_of_views");
334 std::vector<NcDim> dimvec3;
335 dimvec3.push_back(ydim);
336 dimvec3.push_back(xdim);
337 dimvec3.push_back(vdim);
339 NcGroup geo_grp = nc_output->getGroup(
"geolocation_data");
343 double ***time_offsets =
nullptr, toff, toff_fill, toff_min, toff_max;
349 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
350 for (
int v = 0;
v < binl1c->
nviews;
v++) {
351 time_offsets[
i][
j][
v] = 0;
356 NcGroup ba_grp = nc_output->getGroup(
"bin_attributes");
357 NcVar v1 = ba_grp.getVar(
"nadir_view_time");
358 v1.getVar(&binl1c->
time_gd[0]);
360 v1 = ba_grp.getVar(
"view_time_offsets");
361 NcVarAtt a1 = v1.getAtt(
"_FillValue");
362 a1.getValues(&toff_fill);
363 a1 = v1.getAtt(
"valid_min");
364 a1.getValues(&toff_min);
365 a1 = v1.getAtt(
"valid_max");
366 a1.getValues(&toff_max);
370 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
371 for (
int v = 0;
v < binl1c->
nviews;
v++) {
375 if (toff >= toff_min && toff <= toff_max) {
376 time_offsets[
i][
j][
v] = toff;
378 time_offsets[
i][
j][
v] = toff_fill;
380 time_offsets[
i][
j][
v] = toff_fill;
386 v1 = ba_grp.getVar(
"view_time_offsets");
387 v1.putVar(&time_offsets[0][0][0]);
391 v1 = geo_grp.getVar(
"sensor_azimuth_angle");
394 float angleScale = 100.0;
400 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
401 for (
int v = 0;
v < binl1c->
nviews;
v++) {
411 v1.putVar(&temp[0][0][0]);
415 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
416 for (
int v = 0;
v < binl1c->
nviews;
v++) {
426 v1 = geo_grp.getVar(
"sensor_zenith_angle");
427 v1.putVar(&temp[0][0][0]);
431 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
432 for (
int v = 0;
v < binl1c->
nviews;
v++) {
442 v1 = geo_grp.getVar(
"solar_azimuth_angle");
443 v1.putVar(&temp[0][0][0]);
447 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
448 for (
int v = 0;
v < binl1c->
nviews;
v++) {
458 v1 = geo_grp.getVar(
"solar_zenith_angle");
459 v1.putVar(&temp[0][0][0]);
463 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
464 for (
int v = 0;
v < binl1c->
nviews;
v++) {
474 v1 = geo_grp.getVar(
"scattering_angle");
475 v1.putVar(&temp[0][0][0]);
494 NcGroup od_grp = nc_output->getGroup(
"observation_data");
495 v1 = od_grp.getVar(
"number_of_observations");
499 v1.putVar(&binl1c->
nrec_3D[0][0][0]);
505 for (
int j = 0;
j < binl1c->
nbinx;
j++) {
506 for (
int v = 0;
v < binl1c->
nviews;
v++) {
520 v1 = od_grp.getVar(
"i");
521 v1.putVar(&temp2[0][0][0][0]);
530 string senstr, titlestr, prodstr, ifile_str;
533 char *ifile_char =
l1file->name;
535 int16_t
syear, smon,
sday, syear2, smon2, sday2;
537 double tgran_ini, tgran_ini_sec, tgran_end, tgran_end_sec;
540 int16_t y_ini, mo_ini, d_ini, h_ini, mi_ini, y_end, mo_end, d_end, h_end, mi_end;
541 double sec_ini, sec_end;
542 int32_t gransize = 5;
545 if (binl1c->
outlist[0] ==
'\0')
555 cout <<
"writing L1C granules to outfile..." << outxt << endl;
557 std::cerr <<
"output file.." << outxt <<
" could not be opened for writing!\n";
566 titlestr =
"PACE SPEXone Level-1C Data";
571 }
else if (format.type ==
FT_HARP2) {
573 titlestr =
"PACE HARP2 Level-1C Data";
578 }
else if (format.type ==
FT_OCIS) {
580 titlestr =
"PACE OCI Level-1C Data";
586 titlestr =
"PACE OCI Level-1C Data";
593 titlestr =
"PACE OCI Level-1C Data";
600 string l1c_str = l1c_grid;
604 nc_l1cgrid =
new NcFile(l1c_grid, NcFile::read);
605 }
catch (NcException &e) {
607 cerr <<
"l1cgen l1c_pflag= 8:: Failure reading L1C grid: " + l1c_str << endl;
612 NcDim yd = nc_l1cgrid->getDim(
"bins_along_track");
613 int32_t num_gridlines = yd.getSize();
617 binl1c->
nbinx = xbins;
622 NcDim vdim = nc_l1cgrid->getDim(
"number_of_views");
628 NcDim idim = nc_output->getDim(
"intensity_bands_per_view");
632 NcGroup geo_grp = nc_output->getGroup(
"geolocation_data");
633 NcVar v1 = geo_grp.getVar(
"sensor_azimuth_angle");
635 NcVarAtt a1 = v1.getAtt(
"_FillValue");
636 a1.getValues(&
value);
640 NcGroup od_grp = nc_output->getGroup(
"observation_data");
641 v1 = od_grp.getVar(
"i");
643 a1 = v1.getAtt(
"_FillValue");
644 a1.getValues(&value2);
650 nc_output->putAtt(
"processing_version", binl1c->
pversion);
651 if(!binl1c->
doi.empty()) {
652 nc_output->putAtt(
"identifier_product_doi", binl1c->
doi);
653 nc_output->putAtt(
"identifier_product_doi_authority",
"http://dx.doi.org");
656 nc_output->putAtt(
"history", binl1c->
history);
658 nc_output->putAtt(
"product_name", binl1c->
full_l1cgrid);
659 NcGroupAtt i1 = nc_l1cgrid->getAtt(
"startDirection");
661 nc_output->putAtt(
"startDirection",
name);
662 i1 = nc_l1cgrid->getAtt(
"endDirection");
664 nc_output->putAtt(
"endDirection",
name);
665 i1 = nc_l1cgrid->getAtt(
"time_coverage_start");
667 nc_output->putAtt(
"time_coverage_start",
name);
669 i1 = nc_l1cgrid->getAtt(
"time_coverage_end");
672 nc_output->putAtt(
"time_coverage_end",
name);
673 i1 = nc_l1cgrid->getAtt(
"sun_earth_distance");
674 i1.getValues(&value2);
675 nc_output->putAtt(
"sun_earth_distance", ncFloat, value2);
678 unix2ymds(tgran_end, &syear2, &smon2, &sday2, &secs2);
680 tgran_end_sec =
ymds2unix(syear2, smon2, sday2, secs2);
682 unix2ymdhms(tgran_ini_sec, &y_ini, &mo_ini, &d_ini, &h_ini, &mi_ini, &sec_ini);
683 unix2ymdhms(tgran_end_sec, &y_end, &mo_end, &d_end, &h_end, &mi_end, &sec_end);
685 if (mi_end * 60 == 0) {
686 gtime = ((60 * 60 + round(sec_end)) - mi_ini * 60 - round(sec_ini)) / 60;
688 gtime = ((mi_end * 60 + round(sec_end)) - mi_ini * 60 - round(sec_ini)) / 60;
691 if (gtime > gransize) {
692 cout <<
"gtime = " << gtime <<
" is greater than granule size = " << gransize << endl;
695 if ((gtime % gransize) == 0)
701 string secstr = std::to_string(sec_ini);
702 string mistr = std::to_string(mi_ini);
703 string hstr = std::to_string(h_ini);
704 string daystr = std::to_string(d_ini);
705 string monstr = std::to_string(mo_ini);
706 string yearstr = std::to_string(y_ini);
708 int length = (
int)floor(log10(mo_ini)) + 1;
710 monstr =
"0" + monstr;
711 length = (
int)floor(log10(d_ini)) + 1;
713 daystr =
"0" + daystr;
719 length = (
int)floor(log10(h_ini + logoff)) + 1;
726 length = (
int)floor(log10(mi_ini + logoff)) + 1;
733 length = (
int)floor(log10(round(sec_ini + logoff))) + 1;
735 secstr =
"0" + secstr;
737 string fdatetimestr1 = yearstr + monstr + daystr +
"T" + hstr + mistr + secstr.substr(0, 2);
738 string datetimestr1 =
739 yearstr +
"-" + monstr +
"-" + daystr +
"T" + hstr +
":" + mistr +
":" + secstr.substr(0, 2);
742 secstr = std::to_string(sec_end);
743 mistr = std::to_string(mi_end);
744 hstr = std::to_string(h_end);
745 daystr = std::to_string(d_end);
746 monstr = std::to_string(mo_end);
747 yearstr = std::to_string(y_end);
749 length = (
int)floor(log10(mo_end)) + 1;
751 monstr =
"0" + monstr;
752 length = (
int)floor(log10(d_end)) + 1;
754 daystr =
"0" + daystr;
760 length = (
int)floor(log10(h_end + logoff)) + 1;
767 length = (
int)floor(log10(mi_end + logoff)) + 1;
774 length = (
int)floor(log10(round(sec_end + logoff))) + 1;
776 secstr =
"0" + secstr;
778 string datetimestr2 =
779 yearstr +
"-" + monstr +
"-" + daystr +
"T" + hstr +
":" + mistr +
":" + secstr.substr(0, 2);
780 string extstr =
".nc";
782 outf << fname_out_nopath <<
"," << datetimestr1 <<
"," << datetimestr2 <<
"," << gfull <<
"\n";
785 double *time_nad = (
double *)calloc(num_gridlines,
sizeof(
double));
786 NcGroup ba_grp = nc_l1cgrid->getGroup(
"bin_attributes");
787 v1 = ba_grp.getVar(
"nadir_view_time");
790 v1.getAtt(
"units").getValues(tmpUnits);
791 ba_grp = nc_output->getGroup(
"bin_attributes");
792 v1 = ba_grp.getVar(
"nadir_view_time");
793 v1.putVar(&time_nad[0]);
794 if(!tmpUnits.empty())
795 v1.putAtt(
"units", tmpUnits);
796 if (time_nad !=
nullptr)
800 geo_grp = nc_l1cgrid->getGroup(
"geolocation_data");
803 v1 = geo_grp.getVar(
"latitude");
804 v1.getVar(&binl1c->
lat_gd[0][0]);
805 geo_grp = nc_output->getGroup(
"geolocation_data");
806 v1 = geo_grp.getVar(
"latitude");
807 v1.putVar(&binl1c->
lat_gd[0][0]);
809 geo_grp = nc_l1cgrid->getGroup(
"geolocation_data");
810 v1 = geo_grp.getVar(
"longitude");
811 v1.getVar(&binl1c->
lon_gd[0][0]);
812 geo_grp = nc_output->getGroup(
"geolocation_data");
813 v1 = geo_grp.getVar(
"longitude");
814 v1.putVar(&binl1c->
lon_gd[0][0]);
817 geo_grp = nc_l1cgrid->getGroup(
"geolocation_data");
818 v1 = geo_grp.getVar(
"height");
820 v1.getVar(&binl1c->
alt[0][0]);
821 geo_grp = nc_output->getGroup(
"geolocation_data");
822 v1 = geo_grp.getVar(
"height");
823 v1.putVar(&binl1c->
alt[0][0]);
826 string gs_bounds,
crs;
827 float gs_lat_max=-999, gs_lat_min=-999, gs_lon_max=-999, gs_lon_min=-999;
828 i1 = nc_l1cgrid->getAtt(
"geospatial_bounds");
829 i1.getValues(gs_bounds);
830 nc_output->putAtt(
"geospatial_bounds", gs_bounds);
832 i1 = nc_l1cgrid->getAtt(
"geospatial_bounds_crs");
834 nc_output->putAtt(
"geospatial_bounds_crs",
crs);
836 i1 = nc_l1cgrid->getAtt(
"geospatial_lat_max");
837 i1.getValues(&gs_lat_max);
838 nc_output->putAtt(
"geospatial_lat_max", ncFloat, gs_lat_max);
840 i1 = nc_l1cgrid->getAtt(
"geospatial_lat_min");
841 i1.getValues(&gs_lat_min);
842 nc_output->putAtt(
"geospatial_lat_min", ncFloat, gs_lat_min);
844 i1 = nc_l1cgrid->getAtt(
"geospatial_lon_max");
845 i1.getValues(&gs_lon_max);
846 nc_output->putAtt(
"geospatial_lon_max", ncFloat, gs_lon_max);
848 i1 = nc_l1cgrid->getAtt(
"geospatial_lon_min");
849 i1.getValues(&gs_lon_min);
850 nc_output->putAtt(
"geospatial_lon_min", ncFloat, gs_lon_min);
852 std::vector<NcDim> dimvec2_rad;
853 dimvec2_rad.push_back(vdim);
854 dimvec2_rad.push_back(idim);
856 float *Fobar =
l1file->Fobar;
857 float *fwave =
l1file->fwave;
859 float fwave_view[NVIEWS][
NBANDS], fwhm_view[NVIEWS][
NBANDS], Fobar_view[NVIEWS][
NBANDS];
861 for (
int i = 0;
i < NVIEWS;
i++) {
863 fwave_view[
i][
j] = fwave[
j];
864 fwhm_view[
i][
j] = 5.0;
865 Fobar_view[
i][
j] = 10 * Fobar[
j];
870 NcGroup svb_grp = nc_output->getGroup(
"sensor_views_bands");
871 v1 = svb_grp.addVar(
"intensity_wavelength", ncFloat, dimvec2_rad);
872 string longName =
"Intensity field center wavelengths at each view";
873 v1.putAtt(
"long_name", longName);
875 v1.putAtt(
"units",
units);
876 v1.putAtt(
"_FillValue", ncFloat, binl1c->
fillval2);
878 v1.putAtt(
"valid_min", ncFloat,
valid_min);
880 v1.putAtt(
"valid_max", ncFloat,
valid_max);
881 v1.putVar(fwave_view);
884 v1 = svb_grp.addVar(
"intensity_bandpass", ncFloat, dimvec2_rad);
885 longName =
"Intensity field bandpass at each view";
886 v1.putAtt(
"long_name", longName);
888 v1.putAtt(
"units",
units);
889 v1.putAtt(
"_FillValue", ncFloat, binl1c->
fillval2);
891 v1.putAtt(
"valid_min", ncFloat,
valid_min);
893 v1.putAtt(
"valid_max", ncFloat,
valid_max);
894 v1.putVar(fwhm_view);
896 v1 = svb_grp.addVar(
"intensity_f0", ncFloat, dimvec2_rad);
897 longName =
"Intensity band solar irradiance";
898 v1.putAtt(
"long_name", longName);
899 units =
"W m^-2 um^-1";
900 v1.putAtt(
"units",
units);
901 v1.putAtt(
"_FillValue", ncFloat,binl1c->
fillval2);
903 v1.putAtt(
"valid_min", ncFloat,
valid_min);
905 v1.putAtt(
"valid_max", ncFloat,
valid_max);
906 v1.putVar(Fobar_view);
914 string senstr, titlestr, prodstr, ifile_str;
916 int NVIEWS,
NBANDS, NBANDS_POL;
917 int32_t xbins, ybins;
919 ybins = num_gridlines;
921 if (binl1c->
sensor == 34) {
923 titlestr =
"PACE SPEXone Level-1C Data";
924 nadir_bin_index = 14;
929 }
else if (binl1c->
sensor == 35) {
931 titlestr =
"PACE HARP2 Level-1C Data";
932 nadir_bin_index = 228;
937 }
else if (binl1c->
sensor == 30 || binl1c->
sensor == 31) {
939 titlestr =
"PACE OCI Level-1C Data";
940 nadir_bin_index = 259;
947 titlestr =
"PACE OCI Level-1C Data";
948 nadir_bin_index =259;
954 prodstr =
string(gridname);
957 cout <<
"sensor.." << senstr <<
"xbins.." << xbins << endl;
964 nc_output->putAtt(
"title", titlestr);
965 nc_output->putAtt(
"instrument", senstr);
966 nc_output->putAtt(
"Conventions",
"CF-1.8 ACDD-1.3");
967 nc_output->putAtt(
"institution",
"NASA Goddard Space Flight Center, Ocean Biology Processing Group");
968 nc_output->putAtt(
"license",
969 "https://science.nasa.gov/earth-science/earth-science-data/data-information-policy/");
970 nc_output->putAtt(
"naming_authority",
"gov.nasa.gsfc.sci.oceancolor");
971 nc_output->putAtt(
"keywords_vocabulary",
"NASA Global Change Master Directory (GCMD) Science Keywords");
972 nc_output->putAtt(
"stdname_vocabulary",
"NetCDF Climate and Forecast (CF) Metadata Convention");
973 nc_output->putAtt(
"creator_name",
"NASA/GSFC");
974 nc_output->putAtt(
"creator_email",
"data@oceancolor.gsfc.nasa.gov");
975 nc_output->putAtt(
"creator_url",
"https://oceancolor.gsfc.nasa.gov");
976 nc_output->putAtt(
"project",
"PACE Project");
977 nc_output->putAtt(
"publisher_name",
"NASA/GSFC");
978 nc_output->putAtt(
"publisher_email",
"data@oceancolor.gsfc.nasa.gov");
979 nc_output->putAtt(
"publisher_url",
"https://oceancolor.gsfc.nasa.gov");
980 nc_output->putAtt(
"processing_level",
"L1C");
981 nc_output->putAtt(
"cdm_data_type",
"swath");
982 nc_output->putAtt(
"product_name", prodstr);
983 nc_output->putAtt(
"date_created", date_created);
984 nc_output->putAtt(
"sun_earth_distance", ncFloat,
BAD_FLT);
985 nc_output->putAtt(
"nadir_bin", NC_INT,nadir_bin_index);
986 nc_output->putAtt(
"bin_size_at_nadir",
"5.2km2");
988 NcDim ydim = nc_output->addDim(
"bins_along_track", ybins);
989 NcDim xdim = nc_output->addDim(
"bins_across_track", xbins);
990 NcDim vdim = nc_output->addDim(
"number_of_views", NVIEWS);
991 NcDim idim = nc_output->addDim(
"intensity_bands_per_view",
NBANDS);
994 std::vector<NcDim> dimvec2_geo;
995 dimvec2_geo.push_back(ydim);
996 dimvec2_geo.push_back(xdim);
997 std::vector<NcDim> dimvec2_rad;
998 dimvec2_rad.push_back(vdim);
999 dimvec2_rad.push_back(idim);
1000 std::vector<NcDim> dimvec3;
1001 dimvec3.push_back(ydim);
1002 dimvec3.push_back(xdim);
1003 dimvec3.push_back(vdim);
1004 std::vector<NcDim> dimvec4;
1005 dimvec4.push_back(ydim);
1006 dimvec4.push_back(xdim);
1007 dimvec4.push_back(vdim);
1008 dimvec4.push_back(idim);
1011 NcGroup ba_grp = nc_output->addGroup(
"bin_attributes");
1012 NcGroup geo_grp = nc_output->addGroup(
"geolocation_data");
1016 NcDim pdim = nc_output->addDim(
"polarization_bands_per_view", NBANDS_POL);
1017 std::vector<NcDim> dimvec2b_rad;
1018 dimvec2b_rad.push_back(vdim);
1019 dimvec2b_rad.push_back(pdim);
1020 std::vector<NcDim> dimvec4b;
1021 dimvec4b.push_back(ydim);
1022 dimvec4b.push_back(xdim);
1023 dimvec4b.push_back(vdim);
1024 dimvec4b.push_back(pdim);
1027 NcVar v1 = ba_grp.addVar(
"nadir_view_time", ncDouble, ydim);
1028 string longName =
"Time bin was viewed at nadir view";
1029 v1.putAtt(
"long_name", longName);
1030 string units =
"seconds since date";
1031 v1.putAtt(
"units",
units);
1032 v1.putAtt(
"_FillValue", ncDouble, binl1c->
fillval3);
1033 double valid_min_d = 0;
1034 v1.putAtt(
"valid_min", ncDouble, valid_min_d);
1035 double valid_max_d = 172800;
1036 v1.putAtt(
"valid_max", ncDouble, valid_max_d);
1038 v1 = geo_grp.addVar(
"latitude", ncFloat, dimvec2_geo);
1039 longName =
"Latitudes of bin locations";
1040 v1.putAtt(
"long_name", longName);
1041 units =
"degrees_north";
1042 v1.putAtt(
"units",
units);
1043 v1.putAtt(
"_FillValue", ncFloat, binl1c->
fillval2);
1045 v1.putAtt(
"valid_min", ncFloat,
valid_min);
1047 v1.putAtt(
"valid_max", ncFloat,
valid_max);
1049 v1 = geo_grp.addVar(
"longitude", ncFloat, dimvec2_geo);
1050 longName =
"Longitudes of bin locations";
1051 v1.putAtt(
"long_name", longName);
1052 units =
"degrees_east";
1053 v1.putAtt(
"units",
units);
1054 v1.putAtt(
"_FillValue", ncFloat, binl1c->
fillval2);
1056 v1.putAtt(
"valid_min", ncFloat,
valid_min);
1058 v1.putAtt(
"valid_max", ncFloat,
valid_max);
1060 v1 = geo_grp.addVar(
"height", ncShort, dimvec2_geo);
1061 longName =
"Altitude at bin locations";
1062 v1.putAtt(
"long_name", longName);
1064 v1.putAtt(
"units",
units);
1065 v1.putAtt(
"_FillValue", ncShort, binl1c->
fillval1);
1068 short valid_min_s = -10000;
1069 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1071 short valid_max_s = 10000;
1072 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1078 string senstr, GATT_VAL1, prodstr,ifile_str;
1079 string date_created;
1080 int NVIEWS,
NBANDS, NBANDS_POL;
1081 int32_t xbins, ybins;
1082 int nadir_bin_index;
1084 ybins = num_gridlines;
1085 prodstr =
string(gridname);
1093 GATT_VAL1 =
"PACE SPEXone Level-1C Data";
1094 nadir_bin_index =14;
1099 }
else if (format.type ==
FT_HARP2) {
1101 GATT_VAL1 =
"PACE HARP2 Level-1C Data";
1102 nadir_bin_index =228;
1107 }
else if (format.type ==
FT_OCIS) {
1109 GATT_VAL1 =
"PACE OCIS Level-1C Data";
1110 nadir_bin_index =259;
1116 GATT_VAL1 =
"PACE OCI Level-1C Data";
1117 nadir_bin_index =259;
1124 GATT_VAL1 =
"PACE OCI Level-1C Data";
1125 nadir_bin_index =259;
1132 float views[NVIEWS];
1139 }
else if (format.type ==
FT_OCIS) {
1142 }
else if (format.type ==
FT_HARP2) {
1143 cout <<
"# views TBD.....ERROR.." << endl;
1155 nc_output->putAtt(
"title", GATT_VAL1);
1156 nc_output->putAtt(
"instrument", senstr);
1157 nc_output->putAtt(
"Conventions",
"CF-1.8 ACDD-1.3");
1158 nc_output->putAtt(
"institution",
"NASA Goddard Space Flight Center, Ocean Biology Processing Group");
1159 nc_output->putAtt(
"license",
1160 "https://science.nasa.gov/earth-science/earth-science-data/data-information-policy/");
1161 nc_output->putAtt(
"naming_authority",
"gov.nasa.gsfc.sci.oceancolor");
1162 nc_output->putAtt(
"keywords_vocabulary",
"NASA Global Change Master Directory (GCMD) Science Keywords");
1163 nc_output->putAtt(
"stdname_vocabulary",
"NetCDF Climate and Forecast (CF) Metadata Convention");
1164 nc_output->putAtt(
"creator_name",
"NASA/GSFC");
1165 nc_output->putAtt(
"creator_email",
"data@oceancolor.gsfc.nasa.gov");
1166 nc_output->putAtt(
"creator_url",
"https://oceancolor.gsfc.nasa.gov");
1167 nc_output->putAtt(
"project",
"PACE Project");
1168 nc_output->putAtt(
"publisher_name",
"NASA/GSFC");
1169 nc_output->putAtt(
"publisher_email",
"data@oceancolor.gsfc.nasa.gov");
1170 nc_output->putAtt(
"publisher_url",
"https://oceancolor.gsfc.nasa.gov");
1171 nc_output->putAtt(
"processing_level",
"L1C");
1172 nc_output->putAtt(
"cdm_data_type",
"swath");
1173 nc_output->putAtt(
"product_name", prodstr);
1174 nc_output->putAtt(
"date_created", date_created);
1175 nc_output->putAtt(
"sun_earth_distance", ncFloat,
BAD_FLT);
1176 nc_output->putAtt(
"nadir_bin",NC_INT,nadir_bin_index);
1177 nc_output->putAtt(
"bin_size_at_nadir",
"5.2km2");
1179 NcDim ydim = nc_output->addDim(
"bins_along_track", ybins);
1180 NcDim xdim = nc_output->addDim(
"bins_across_track", xbins);
1181 NcDim vdim = nc_output->addDim(
"number_of_views", NVIEWS);
1182 NcDim idim = nc_output->addDim(
"intensity_bands_per_view",
NBANDS);
1185 std::vector<NcDim> dimvec2_geo;
1186 dimvec2_geo.push_back(ydim);
1187 dimvec2_geo.push_back(xdim);
1188 std::vector<NcDim> dimvec2_rad;
1189 dimvec2_rad.push_back(vdim);
1190 dimvec2_rad.push_back(idim);
1191 std::vector<NcDim> dimvec3;
1192 dimvec3.push_back(ydim);
1193 dimvec3.push_back(xdim);
1194 dimvec3.push_back(vdim);
1195 std::vector<NcDim> dimvec4;
1196 dimvec4.push_back(ydim);
1197 dimvec4.push_back(xdim);
1198 dimvec4.push_back(vdim);
1199 dimvec4.push_back(idim);
1202 NcGroup svb_grp = nc_output->addGroup(
"sensor_views_bands");
1203 NcGroup ba_grp = nc_output->addGroup(
"bin_attributes");
1204 NcGroup geo_grp = nc_output->addGroup(
"geolocation_data");
1205 NcGroup od_grp = nc_output->addGroup(
"observation_data");
1209 NcVar v1 = svb_grp.addVar(
"sensor_view_angle", ncFloat, vdim);
1210 string longName =
"Along-track view angles for sensor";
1211 v1.putAtt(
"long_name", longName);
1212 string units =
"degrees";
1213 v1.putAtt(
"units",
units);
1214 v1.putAtt(
"_FillValue", ncFloat,binl1c->
fillval2);
1216 v1.putAtt(
"valid_min", ncFloat,
valid_min);
1218 v1.putAtt(
"valid_max", ncFloat,
valid_max);
1223 NcDim pdim = nc_output->addDim(
"polarization_bands_per_view", NBANDS_POL);
1224 std::vector<NcDim> dimvec2b_rad;
1225 dimvec2b_rad.push_back(vdim);
1226 dimvec2b_rad.push_back(pdim);
1227 std::vector<NcDim> dimvec4b;
1228 dimvec4b.push_back(ydim);
1229 dimvec4b.push_back(xdim);
1230 dimvec4b.push_back(vdim);
1231 dimvec4b.push_back(pdim);
1234 v1 = ba_grp.addVar(
"nadir_view_time", ncDouble, ydim);
1235 longName =
"Time bin was viewed at nadir view";
1236 v1.putAtt(
"long_name", longName);
1237 units =
"seconds since date";
1238 v1.putAtt(
"units",
units);
1239 v1.putAtt(
"_FillValue", ncDouble, binl1c->
fillval3);
1240 double valid_min_d = 0;
1241 v1.putAtt(
"valid_min", ncDouble, valid_min_d);
1242 double valid_max_d = 172800;
1243 v1.putAtt(
"valid_max", ncDouble, valid_max_d);
1245 v1 = ba_grp.addVar(
"view_time_offsets", ncDouble, dimvec3);
1246 longName =
"Time offsets of views from nadir view";
1247 v1.putAtt(
"long_name", longName);
1249 v1.putAtt(
"units",
units);
1250 v1.putAtt(
"_FillValue", ncDouble, binl1c->
fillval3);
1252 v1.putAtt(
"valid_min", ncDouble, valid_min_d);
1254 v1.putAtt(
"valid_max", ncDouble, valid_max_d);
1256 v1 = geo_grp.addVar(
"latitude", ncFloat, dimvec2_geo);
1257 longName =
"Latitudes of bin locations";
1258 v1.putAtt(
"long_name", longName);
1259 units =
"degrees_north";
1260 v1.putAtt(
"units",
units);
1261 v1.putAtt(
"_FillValue", ncFloat,binl1c->
fillval2);
1263 v1.putAtt(
"valid_min", ncFloat,
valid_min);
1265 v1.putAtt(
"valid_max", ncFloat,
valid_max);
1267 v1 = geo_grp.addVar(
"longitude", ncFloat, dimvec2_geo);
1268 longName =
"Longitudes of bin locations";
1269 v1.putAtt(
"long_name", longName);
1270 units =
"degrees_east";
1271 v1.putAtt(
"units",
units);
1272 v1.putAtt(
"_FillValue", ncFloat, binl1c->
fillval2);
1274 v1.putAtt(
"valid_min", ncFloat,
valid_min);
1276 v1.putAtt(
"valid_max", ncFloat,
valid_max);
1278 v1 = geo_grp.addVar(
"height", ncShort, dimvec2_geo);
1279 longName =
"Altitude at bin locations";
1280 v1.putAtt(
"long_name", longName);
1282 v1.putAtt(
"units",
units);
1283 v1.putAtt(
"_FillValue", ncShort,binl1c->
fillval1);
1286 short valid_min_s = -10000;
1287 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1289 short valid_max_s=10000;
1290 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1292 v1 = geo_grp.addVar(
"height_stdev", ncShort, dimvec2_geo);
1293 longName =
"Standard deviation of terrain altitude within bin";
1294 v1.putAtt(
"long_name", longName);
1296 v1.putAtt(
"units",
units);
1297 v1.putAtt(
"_FillValue", ncShort, binl1c->
fillval1);
1299 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1301 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1303 v1 = geo_grp.addVar(
"sensor_azimuth_angle", ncShort, dimvec3);
1304 longName =
"Sensor azimuth angles at bin locations";
1305 v1.putAtt(
"long_name", longName);
1307 v1.putAtt(
"units",
units);
1308 v1.putAtt(
"_FillValue", ncShort, binl1c->
fillval1);
1309 valid_min_s = -18000;
1310 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1311 valid_max_s = 18000;
1312 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1313 float scale_factor = 0.01;
1314 v1.putAtt(
"scale_factor", ncFloat, scale_factor);
1315 float add_offset = 0;
1316 v1.putAtt(
"add_offset", ncFloat, add_offset);
1318 v1 = geo_grp.addVar(
"sensor_zenith_angle", ncShort, dimvec3);
1319 longName =
"Sensor zenith angles at bin locations";
1320 v1.putAtt(
"long_name", longName);
1322 v1.putAtt(
"units",
units);
1323 v1.putAtt(
"_FillValue", ncShort,binl1c->
fillval1);
1325 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1326 valid_max_s = 18000;
1327 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1328 scale_factor = 0.01;
1329 v1.putAtt(
"scale_factor", ncFloat, scale_factor);
1331 v1.putAtt(
"add_offset", ncFloat, add_offset);
1333 v1 = geo_grp.addVar(
"solar_azimuth_angle", ncShort, dimvec3);
1334 longName =
"Solar azimuth angle at bin locations";
1335 v1.putAtt(
"long_name", longName);
1337 v1.putAtt(
"units",
units);
1338 v1.putAtt(
"_FillValue", ncShort,binl1c->
fillval1);
1339 valid_min_s = -18000;
1340 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1341 valid_max_s = 18000;
1342 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1343 scale_factor = 0.01;
1344 v1.putAtt(
"scale_factor", ncFloat, scale_factor);
1346 v1.putAtt(
"add_offset", ncFloat, add_offset);
1348 v1 = geo_grp.addVar(
"solar_zenith_angle", ncShort, dimvec3);
1349 longName =
"Solar zenith angle at bin locations";
1350 v1.putAtt(
"long_name", longName);
1352 v1.putAtt(
"units",
units);
1353 v1.putAtt(
"_FillValue", ncShort,binl1c->
fillval1);
1355 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1356 valid_max_s = 18000;
1357 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1358 scale_factor = 0.01;
1359 v1.putAtt(
"scale_factor", ncFloat, scale_factor);
1361 v1.putAtt(
"add_offset", ncFloat, add_offset);
1363 v1 = geo_grp.addVar(
"scattering_angle", ncShort, dimvec3);
1364 longName =
"Scattering angle at bin locations";
1365 v1.putAtt(
"long_name", longName);
1367 v1.putAtt(
"units",
units);
1368 v1.putAtt(
"_FillValue", ncShort,binl1c->
fillval1);
1370 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1371 valid_max_s = 18000;
1372 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1373 scale_factor = 0.01;
1374 v1.putAtt(
"scale_factor", ncFloat, scale_factor);
1376 v1.putAtt(
"add_offset", ncFloat, add_offset);
1393 v1 = od_grp.addVar(
"number_of_observations", ncShort, dimvec3);
1394 longName =
"Observations contributing to bin from each view";
1395 v1.putAtt(
"long_name", longName);
1397 v1.putAtt(
"valid_min", ncShort, valid_min_s);
1399 v1.putAtt(
"valid_max", ncShort, valid_max_s);
1400 v1.putAtt(
"coordinates",
"geolocation_data/longitude geolocation_data/latitude");
1403 uint8_t FillValue3, valid_min2, valid_max2;
1405 v1 = od_grp.addVar(
"qc", ncUbyte, dimvec4);
1406 longName =
"quality indicator";
1407 v1.putAtt(
"long_name", longName);
1409 v1.putAtt(
"_FillValue", ncUbyte, FillValue3);
1411 v1.putAtt(
"valid_min", ncUbyte, valid_min2);
1413 v1.putAtt(
"valid_max", ncUbyte, valid_max2);
1414 v1.putAtt(
"coordinates",
"geolocation_data/longitude geolocation_data/latitude");
1416 v1 = od_grp.addVar(
"i", ncFloat, dimvec4);
1417 longName =
"I Stokes vector component";
1418 v1.putAtt(
"long_name", longName);
1419 units =
"W m^-2 sr^-1 um^-1";
1420 v1.putAtt(
"units",
units);
1421 v1.putAtt(
"_FillValue", ncFloat, binl1c->
fillval2);
1423 v1.putAtt(
"valid_min", ncFloat,
valid_min);
1425 v1.putAtt(
"valid_max", ncFloat,
valid_max);
1426 v1.putAtt(
"coordinates",
"geolocation_data/longitude geolocation_data/latitude");
1428 v1 = od_grp.addVar(
"i_stdev", ncFloat, dimvec4);
1429 longName =
"Random stdev of i in bin";
1430 v1.putAtt(
"long_name", longName);
1431 units =
"W m^-2 sr^-1 um^-1";
1432 v1.putAtt(
"units",
units);
1433 v1.putAtt(
"_FillValue", ncFloat,binl1c->
fillval2);
1435 v1.putAtt(
"valid_min", ncFloat,
valid_min);
1437 v1.putAtt(
"valid_max", ncFloat,
valid_max);
1438 v1.putAtt(
"coordinates",
"geolocation_data/longitude geolocation_data/latitude");
1448 NcFile *nc_output) {
1449 short gd_row = -1, gd_col = -1;
1452 double timefill, mintime, maxtime;
1453 float fill_tilt = binstr->
fillval2;
1456 NcGroup ba_grp = nc_output->getGroup(
"bin_attributes");
1457 NcVar v1 = ba_grp.getVar(
"nadir_view_time");
1458 NcVarAtt a1 = v1.getAtt(
"_FillValue");
1459 a1.getValues(&timefill);
1460 a1 = v1.getAtt(
"valid_min");
1461 a1.getValues(&mintime);
1462 a1 = v1.getAtt(
"valid_max");
1463 a1.getValues(&maxtime);
1466 for (
int pix = 0; pix <
npix; pix++) {
1467 gd_row = gdindex[pix][0] - 1;
1468 gd_col = gdindex[pix][1] - 1;
1473 if (
l1rec->tilt != fill_tilt &&
l1rec->tilt < -18) {
1476 }
else if (
l1rec->tilt != fill_tilt &&
l1rec->tilt > 18) {
1481 if (gd_row >= 2000) {
1500 if (view !=
BAD_FLT &&
tilt != fill_tilt && gd_row >= 0 && gd_col >= 0 &&
1501 gd_row <= binstr->num_gridlines - 1 && gd_col <= binstr->nbinx - 1 && scantime != timefill &&
1502 scantime >= mintime && scantime <= maxtime) {
1503 binstr->
time_l1b[gd_row][gd_col][view] = binstr->
time_l1b[gd_row][gd_col][view] + scantime;
1514 short **gdindex, NcFile *nc_output,int32_t sline,
int firstcall) {
1515 short gd_row = -1, gd_col = -1;
1516 string l1c_str = l1c_grid;
1517 string l1c_str2 = l1c_anc;
1518 float *lat_new =
nullptr, *lon_new =
nullptr;
1519 float dv,
Re = 6378.137, Hsat = 676.5;
1520 float **cth =
nullptr, **height =
nullptr;
1522 short sena_min, sena_max, senz_min, senz_max;
1524 float look_angle,*scan_angle=
nullptr;
1526 size_t start[] = { 0, 0,};
1527 size_t count[] = { 1, 1 };
1533 if(firstcall==0){ scan_angle = (
float*)calloc(
l1file->npix,
sizeof(
float));firstcall=1;}
1537 status = nc_inq_grp_ncid(
l1file->sd_id,
"navigation_data", &navGrp);
1539 status = nc_inq_varid(navGrp,
"CCD_scan_angles", &scangId);
1546 nc_l1cgrid =
new NcFile(l1c_grid, NcFile::read);
1547 }
catch (NcException &e) {
1549 cerr <<
"l1cgen l1c_pflag= 8:: Failure reading L1C grid: " + l1c_str << endl;
1553 NcDim yd1 = nc_l1cgrid->getDim(
"bins_along_track");
1554 NcDim xd1 = nc_l1cgrid->getDim(
"bins_across_track");
1556 NcGroup geo_grp = nc_l1cgrid->getGroup(
"geolocation_data");
1557 NcVar v1 = geo_grp.getVar(
"height");
1559 v1.getVar(&height[0][0]);
1565 nc_l1canc =
new NcFile(l1c_anc, NcFile::read);
1566 }
catch (NcException &e) {
1568 cerr <<
"l1cgen l1c_pflag= 8:: Failure reading L1C-ANCfile: " + l1c_str2 << endl;
1573 NcDim yd2 = nc_l1canc->getDim(
"bins_along_track");
1574 NcDim xd2 = nc_l1canc->getDim(
"bins_across_track");
1577 v1 = nc_l1canc->getVar(
"cth_water_cloud");
1578 v1.getVar(&cth[0][0]);
1581 v1 = nc_l1canc->getVar(
"cth_ice_cloud");
1582 v1.getVar(&cth[0][0]);
1588 NcGroup geo_grp2 = nc_output->getGroup(
"geolocation_data");
1589 v1 = geo_grp2.getVar(
"sensor_azimuth_angle");
1590 NcVarAtt a1 = v1.getAtt(
"scale_factor");
1591 a1.getValues(&scale_factor);
1592 a1 = v1.getAtt(
"valid_min");
1593 a1.getValues(&sena_min);
1594 sena_min *= scale_factor;
1595 a1 = v1.getAtt(
"valid_max");
1596 a1.getValues(&sena_max);
1597 sena_max *= scale_factor;
1598 v1 = geo_grp2.getVar(
"sensor_zenith_angle");
1599 a1 = v1.getAtt(
"scale_factor");
1600 a1.getValues(&scale_factor);
1601 a1 = v1.getAtt(
"valid_min");
1602 a1.getValues(&senz_min);
1603 senz_min *= scale_factor;
1604 a1 = v1.getAtt(
"valid_max");
1605 a1.getValues(&senz_max);
1606 senz_max *= scale_factor;
1608 lat_new = (
float *)calloc(
l1file->npix,
sizeof(
float));
1609 lon_new = (
float *)calloc(
l1file->npix,
sizeof(
float));
1611 for (
int pix = 0; pix <
l1file->npix; pix++) {
1612 gd_row = gdindex[pix][0] - 1;
1613 gd_col = gdindex[pix][1] - 1;
1616 l1rec->sena[pix] <= sena_max) {
1617 look_angle=acos(cos(
l1rec->tilt *
M_PI / 180)*cos(scan_angle[pix]*
M_PI/180));
1620 dv = Hsat * cth[gd_row][gd_col] * tan(look_angle) /
1621 (Hsat - cth[gd_row][gd_col]);
1624 dv = Hsat * 0.001 *
l1rec->height[pix] * tan(look_angle) /
1625 (Hsat - 0.001 *
l1rec->height[pix]);
1630 (
Re * cos(lat_new[pix] *
M_PI / 180));
1632 if (lon_new[pix] * 180 /
M_PI > 180) {
1633 lon_new[pix] -= 2 *
M_PI;
1635 if (lon_new[pix] * 180 /
M_PI < -180) {
1636 lon_new[pix] += 2 *
M_PI;
1638 lat_new[pix] *= 180 /
M_PI;
1639 lon_new[pix] *= 180 /
M_PI;
1644 if(pix==635 && binl1c->
verbose) cout<<
"sline # "<<sline+1<<
"look_angle in m "<<look_angle*180/
M_PI<<
"dv "<<dv<<
"scan_angle "<<180/
M_PI*scan_angle[pix]<<
"lat_new "<<lat_new[pix]<<
"lon_new "<<lon_new[pix]<<
"height "<<
l1rec->height[pix]<<endl;
1650 nc_l1cgrid->close();
1654 if (height !=
nullptr)
1656 if (lat_new !=
nullptr)
1658 if (lon_new !=
nullptr)
1661 if(sline==
l1file->nscan-1){
if (scan_angle !=
nullptr) free(scan_angle);}
1667 int32_t ibp = 0,
sb = 0;
1668 short gd_row = -1, gd_col = -1;
1674 float term1, term2, term3, sca_pix, cosu, cose;
1675 float scale_all[7], offset_all[7];
1676 short minval1_all[7], maxval1_all[7];
1677 float minval2_all[7], maxval2_all[7];
1678 float fill_tilt = binl1c->
fillval2;
1679 short fill_height = binl1c->
fillval2;
1683 NcGroup geo_grp = nc_output->getGroup(
"geolocation_data");
1684 NcGroup od_grp = nc_output->getGroup(
"observation_data");
1687 NcVar v1 = geo_grp.getVar(
"height");
1690 NcVarAtt a1 = v1.getAtt(
"valid_min");
1691 a1.getValues(&minval1_all[0]);
1692 a1 = v1.getAtt(
"valid_max");
1693 a1.getValues(&maxval1_all[0]);
1696 v1 = geo_grp.getVar(
"sensor_azimuth_angle");
1697 a1 = v1.getAtt(
"scale_factor");
1698 a1.getValues(&scale_all[1]);
1699 a1 = v1.getAtt(
"add_offset");
1700 a1.getValues(&offset_all[1]);
1701 a1 = v1.getAtt(
"valid_min");
1702 a1.getValues(&minval1_all[1]);
1703 a1 = v1.getAtt(
"valid_max");
1704 a1.getValues(&maxval1_all[1]);
1707 v1 = geo_grp.getVar(
"sensor_zenith_angle");
1708 a1 = v1.getAtt(
"scale_factor");
1709 a1.getValues(&scale_all[2]);
1710 a1 = v1.getAtt(
"add_offset");
1711 a1.getValues(&offset_all[2]);
1712 a1 = v1.getAtt(
"valid_min");
1713 a1.getValues(&minval1_all[2]);
1714 a1 = v1.getAtt(
"valid_max");
1715 a1.getValues(&maxval1_all[2]);
1717 minval1_all[2] = scale_all[2] * minval1_all[2] + offset_all[2];
1718 maxval1_all[2] = scale_all[2] * maxval1_all[2] + offset_all[2];
1721 v1 = geo_grp.getVar(
"solar_azimuth_angle");
1722 a1 = v1.getAtt(
"scale_factor");
1723 a1.getValues(&scale_all[3]);
1724 a1 = v1.getAtt(
"add_offset");
1725 a1.getValues(&offset_all[3]);
1726 a1 = v1.getAtt(
"valid_min");
1727 a1.getValues(&minval1_all[3]);
1728 a1 = v1.getAtt(
"valid_max");
1729 a1.getValues(&maxval1_all[3]);
1732 v1 = geo_grp.getVar(
"solar_zenith_angle");
1733 a1 = v1.getAtt(
"scale_factor");
1734 a1.getValues(&scale_all[4]);
1735 a1 = v1.getAtt(
"add_offset");
1736 a1.getValues(&offset_all[4]);
1737 a1 = v1.getAtt(
"valid_min");
1738 a1.getValues(&minval1_all[4]);
1739 a1 = v1.getAtt(
"valid_max");
1740 a1.getValues(&maxval1_all[4]);
1743 v1 = geo_grp.getVar(
"scattering_angle");
1744 a1 = v1.getAtt(
"scale_factor");
1745 a1.getValues(&scale_all[5]);
1746 a1 = v1.getAtt(
"add_offset");
1747 a1.getValues(&offset_all[5]);
1748 a1 = v1.getAtt(
"valid_min");
1749 a1.getValues(&minval1_all[5]);
1750 a1 = v1.getAtt(
"valid_max");
1751 a1.getValues(&maxval1_all[5]);
1765 v1 = od_grp.getVar(
"i");
1766 a1 = v1.getAtt(
"valid_min");
1767 a1.getValues(&minval2_all[0]);
1768 a1 = v1.getAtt(
"valid_max");
1769 a1.getValues(&maxval2_all[0]);
1771 for (
int pix = 0; pix <
npix; pix++) {
1772 gd_row = gdindex[pix][0] - 1;
1773 gd_col = gdindex[pix][1] - 1;
1777 if (
l1rec->tilt != fill_tilt &&
l1rec->tilt < -18) {
1780 }
else if (
l1rec->tilt != fill_tilt &&
l1rec->tilt > 18) {
1784 if (gd_row >= 2000) {
1800 if (view !=
BAD_FLT &&
tilt != fill_tilt && gd_row >= 0 && gd_col >= 0 &&
1801 gd_row <= binl1c->num_gridlines - 1 && gd_col <= binl1c->nbinx - 1 &&
1803 if (
l1rec->height[pix] != fill_height)
1805 binl1c->
nrec_2D[gd_row][gd_col] += 1;
1806 binl1c->
alt_2D[gd_row][gd_col] =
1807 binl1c->
alt_2D[gd_row][gd_col] +
l1rec->height[pix];
1817 if (view !=
BAD_FLT &&
tilt != fill_tilt && gd_row >= 0 && gd_col >= 0 &&
1818 gd_row <= binl1c->num_gridlines - 1 && gd_col <= binl1c->nbinx - 1 &&
1820 l1rec->senz[pix] <= maxval1_all[2]) {
1821 binl1c->
nrec_3D[gd_row][gd_col][view] += 1;
1822 binl1c->
sena_3D[gd_row][gd_col][view] = binl1c->
sena_3D[gd_row][gd_col][view] +
l1rec->sena[pix];
1823 binl1c->
senz_3D[gd_row][gd_col][view] =
1824 binl1c->
senz_3D[gd_row][gd_col][view] +
l1rec->senz[pix];
1825 binl1c->
suna_3D[gd_row][gd_col][view] = binl1c->
suna_3D[gd_row][gd_col][view] +
l1rec->sola[pix];
1826 binl1c->
sunz_3D[gd_row][gd_col][view] = binl1c->
sunz_3D[gd_row][gd_col][view] +
l1rec->solz[pix];
1828 cose = cos((
l1rec->senz[pix] + 180) *
M_PI / 180);
1829 cosu = cos((
l1rec->solz[pix]) *
M_PI / 180);
1830 term1 = cose * cosu;
1831 term2 = sqrt((1 - cose * cose)) * sqrt((1 - cosu * cosu));
1832 term3 = cos((
l1rec->sena[pix] + 180 -
l1rec->sola[pix]) *
M_PI / 180);
1833 sca_pix = acos(term1 + term2 * term3) * 180 /
M_PI;
1834 binl1c->
sca_3D[gd_row][gd_col][view] = binl1c->
sca_3D[gd_row][gd_col][view] + sca_pix;
1837 binl1c->
rot_angle[gd_row][gd_col][view] = binl1c->
rot_angle[gd_row][gd_col][view] + rotangle;
1843 if (view !=
BAD_FLT &&
tilt != fill_tilt && gd_row >= 0 && gd_col >= 0 &&
1844 gd_row <= binl1c->num_gridlines - 1 && gd_col <= binl1c->nbinx - 1 &&
l1rec->Lt[ibp] != binl1c->
fillval2 &&
l1rec->Lt[ibp] >= minval2_all[0] && 10 *
l1rec->Lt[ibp] <= maxval2_all[0]){
1850 binl1c->
I_4D[gd_row][gd_col][view][
sb] =
1851 binl1c->
I_4D[gd_row][gd_col][view][
sb] + 10 *
l1rec->Lt[ibp];
1855 if(binl1c->
i_diff2[gd_row][gd_col][view][
sb]==0)
1857 seed_mean=10 *
l1rec->Lt[ibp];
1858 binl1c->
i_diff2[gd_row][gd_col][view][
sb]=0.01;
1861 binl1c->
i_diff2[gd_row][gd_col][view][
sb]+=(10 *
l1rec->Lt[ibp]-seed_mean)*(10 *
l1rec->Lt[ibp]-seed_mean);
1866 cout <<
"ERROR IN BINNING Lt/rhot --gd_row/gd-col outside the grid limits" << endl;
1867 cout <<
"row.." << gd_row <<
"gd_col.." << gd_col << endl;
1881 string l1c_str = l1c_grid;
1882 string l1b_str = l1b_file;
1886 nc_l1cgrid =
new NcFile(l1c_grid, NcFile::read);
1887 }
catch (NcException &e) {
1889 cerr <<
"l1cgen l1c_pflag= 8:: Failure reading L1C grid: " + l1c_str << endl;
1893 NcDim yd = nc_l1cgrid->getDim(
"bins_along_track");
1894 int32_t num_gridlines = yd.getSize();
1895 double *time_nad_l1c = (
double *)calloc(num_gridlines,
sizeof(
double));
1896 NcGroup ba_grp = nc_l1cgrid->getGroup(
"bin_attributes");
1897 NcVar v1 = ba_grp.getVar(
"nadir_view_time");
1898 v1.getVar(time_nad_l1c);
1903 nc_l1b =
new NcFile(l1b_file, NcFile::read);
1904 }
catch (NcException &e) {
1906 cerr <<
"l1cgen l1c_pflag= 8:: Failure reading L1B or L1C-ANCfile: " + l1b_str << endl;
1913 if (binl1c->
l1c_anc[0] !=
'\0' && strcmp(binl1c->
l1c_anc, l1b_file) == 0) {
1915 cout <<
"L1C ANC file provided" << endl;
1916 yd = nc_l1b->getDim(
"bins_along_track");
1917 int32_t num_gridlines2 = yd.getSize();
1918 nscans = num_gridlines2;
1920 if (num_gridlines != num_gridlines2) {
1921 cerr <<
"WARNING number of gridlines ARE NOT THE SAME IN L1C grid and ANC files"
1922 <<
"L1C grid # " << num_gridlines <<
"ANC file # " << num_gridlines2 << endl;
1926 yd = nc_l1b->getDim(
"number_of_scans");
1927 nscans = yd.getSize();
1930 double tend_l1b, *time_l1b =
nullptr;
1932 if (binl1c->
l1c_anc[0] ==
'\0' || strcmp(binl1c->
l1c_anc, l1b_file) != 0) {
1933 time_l1b = (
double *)calloc(nscans,
sizeof(
double));
1934 NcGroup sla_grp = nc_l1b->getGroup(
"scan_line_attributes");
1935 v1 = sla_grp.getVar(
"time");
1936 v1.getVar(time_l1b);
1937 tend_l1b = time_l1b[nscans - 1];
1939 time_l1b = time_nad_l1c;
1940 tend_l1b = time_l1b[nscans - 2];
1944 double tini_l1c = time_nad_l1c[0];
1945 double tend_l1c = time_nad_l1c[num_gridlines - 1];
1946 double tini_l1b = time_l1b[0];
1954 if (tini_l1b > (tini_l1c - 5 * 60 - 1) && tini_l1b < (tend_l1c + 5 * 60 + 1)) {
1957 cout <<
"OK--L1B granule is INSIDE of the L1C grid--" << endl;
1958 cout <<
"tini_l1c.." << tini_l1c <<
"tend_l1c.." << tend_l1c <<
"tini_l1b.." << tini_l1b
1959 <<
"tend_l1b.." << tend_l1b << endl;
1960 cout <<
"tini_l1c-5*60" << tini_l1c - 5 * 60 <<
"tend_l1c+5*60" << tend_l1c + 5 * 60 << endl;
1965 cout <<
"ERROR--L1B granule is outside of the L1C grid--" << endl;
1966 cout <<
"tini_l1c.." << tini_l1c <<
"tend_l1c.." << tend_l1c <<
"tini_l1b.." << tini_l1b
1967 <<
"tend_l1b.." << tend_l1b << endl;
1968 cout <<
"tini_l1c-5*60" << tini_l1c - 5 * 60 <<
"tend_l1c+5*60" << tend_l1c + 5 * 60 << endl;
1972 if (time_nad_l1c !=
nullptr)
1974 time_nad_l1c =
nullptr;
1976 if (binl1c->
l1c_anc[0] ==
'\0' || strcmp(binl1c->
l1c_anc, l1b_file) != 0) {
1977 if (time_l1b !=
nullptr)
1982 nc_l1cgrid->close();
1988 int open_l1c(
const char *ifile_l1c,
size_t *ybins,
size_t *xbins,
float **lat_gd,
float **lon_gd) {
1991 string gridname, azeast_name;
1992 std::string fname_out, pathstr, senstr, monstr, daystr, yearstr, prodstr, gdstr, swtstr, swtnum, extstr,
1993 granstr, timestr, azstr, missionstr, ofilestr;
1997 string l1c_str(ifile_l1c);
2002 nc_l1cgrid =
new NcFile(ifile_l1c, NcFile::read);
2003 }
catch (NcException &e) {
2005 cerr <<
"l1cgen :: Failure reading L1C grid: " + l1c_str << endl;
2008 NcGroup geo_grp = nc_l1cgrid->getGroup(
"geolocation_data");
2009 NcVar v1 = geo_grp.getVar(
"latitude");
2010 v1.getVar(&lat_gd[0][0]);
2011 v1 = geo_grp.getVar(
"longitude");
2012 v1.getVar(&lon_gd[0][0]);
2014 nc_l1cgrid->close();
2022 string gridname, azeast_name;
2023 std::string fname_out, pathstr, senstr, monstr, daystr, yearstr, prodstr, gdstr, swtstr, swtnum, extstr,
2024 granstr, timestr, azstr, missionstr, ofilestr;
2028 string l1c_str(ifile_l1c);
2033 nc_l1cgrid =
new NcFile(ifile_l1c, NcFile::read);
2034 }
catch (NcException &e) {
2036 cerr <<
"l1cgen :: Failure reading L1C grid: " + l1c_str << endl;
2039 NcGroup geo_grp = nc_l1cgrid->getGroup(
"geolocation_data");
2040 NcVar v1 = geo_grp.getVar(
"latitude");
2041 v1.getVar(&lat_gd[0][0]);
2042 v1 = geo_grp.getVar(
"longitude");
2043 v1.getVar(&lon_gd[0][0]);
2044 v1 = geo_grp.getVar(
"height");
2045 v1.getVar(&alt_gd[0][0]);
2047 NcDim ydim = nc_l1cgrid->getDim(
"bins_along_track");
2048 NcDim xdim = nc_l1cgrid->getDim(
"bins_across_track");
2050 binl1c->
nbinx = xdim.getSize();
2052 nc_l1cgrid->close();
2059 int32_t nbinx = binl1c->
nbinx;
2064 if (binl1c->
lat_gd[gridline][nbinx - 1] > 90 || binl1c->
lat_gd[gridline][nbinx - 1] < -90 ||
2065 binl1c->
lon_gd[gridline][nbinx - 1] < -180 || binl1c->
lon_gd[gridline][nbinx - 1] > 180) {
2067 cout <<
"lat lon for L1C GRID out of the boundaries.." << endl;
2070 if (binl1c->
lat_gd[gridline][0] > 90 || binl1c->
lat_gd[gridline][0] < -90 || binl1c->
lon_gd[gridline][0] < -180 ||
2071 binl1c->
lon_gd[gridline][0] > 180) {
2073 cout <<
"lat lon for L1C GRID out of the boundaries.." << endl;
2077 gnvec[0] = sin(binl1c->
lon_gd[gridline][nbinx - 1] *
M_PI / 180) *
2078 cos(binl1c->
lat_gd[gridline][nbinx - 1] *
M_PI / 180) *
2079 sin(binl1c->
lat_gd[gridline][0] *
M_PI / 180) -
2080 sin(binl1c->
lat_gd[gridline][nbinx - 1] *
M_PI / 180) *
2082 gnvec[1] = sin(binl1c->
lat_gd[gridline][nbinx - 1] *
M_PI / 180) *
2083 cos(binl1c->
lon_gd[gridline][0] *
M_PI / 180) * cos(binl1c->
lat_gd[gridline][0] *
M_PI / 180) -
2084 cos(binl1c->
lon_gd[gridline][nbinx - 1] *
M_PI / 180) *
2085 cos(binl1c->
lat_gd[gridline][nbinx - 1] *
M_PI / 180) *
2086 sin(binl1c->
lat_gd[gridline][0] *
M_PI / 180);
2087 gnvec[2] = cos(binl1c->
lon_gd[gridline][nbinx - 1] *
M_PI / 180) *
2088 cos(binl1c->
lat_gd[gridline][nbinx - 1] *
M_PI / 180) *
2089 sin(binl1c->
lon_gd[gridline][0] *
M_PI / 180) * cos(binl1c->
lat_gd[gridline][0] *
M_PI / 180) -
2090 sin(binl1c->
lon_gd[gridline][nbinx - 1] *
M_PI / 180) *
2091 cos(binl1c->
lat_gd[gridline][nbinx - 1] *
M_PI / 180) *
2095 gnvm = sqrt(gnvec[0] * gnvec[0] + gnvec[1] * gnvec[1] + gnvec[2] * gnvec[2]);
2096 if (isnan(gnvm) == 1) {
2098 cout <<
"NAN value for gnvm.." << endl;
2103 cout <<
"ERROR gnvm == 0--- WE CANT NORMALIZE..." << endl;
2107 gnvec[0] = gnvec[0] / gnvm;
2108 gnvec[1] = gnvec[1] / gnvm;
2109 gnvec[2] = gnvec[2] / gnvm;
2113 return gnvec[0] * bvec[0] + gnvec[1] * bvec[1] + gnvec[2] * bvec[2];
2121 int32_t num_gridlines, nbinx;
2126 int irow = -1, col = -1;
2127 float bmcm, bm = 100;
2130 double dotprod, dot_firstline, dot_lastline;
2131 int32_t last_dotprod_index = 0;
2132 double last_dotprod;
2133 float gvec[3], bvec[3];
2136 nbinx = binl1c->
nbinx;
2137 num_pixels =
l1file->npix;
2138 db = (5.2) / 6371 / 2;
2139 double db_fudge =
db * 1.5;
2143 for (pix = 0; pix < num_pixels; pix++) {
2144 gdindex[pix][0] = -1;
2145 gdindex[pix][1] = -1;
2147 if (lat_new[pix] > 90 || lat_new[pix] < -90 || lon_new[pix] < -180 || lon_new[pix] > 180 ||
2151 <<
"ERROR in search_l1cgen --latitude longitude pixel out of the boundaries.OR FILLVALUE."
2152 <<
"latpix>90 or <-90.." << lat_new[pix] <<
"lonpix>180 or <-180.." << lon_new[pix]
2157 bvec[0] = cos(lon_new[pix] *
M_PI / 180) * cos(lat_new[pix] *
M_PI / 180);
2158 bvec[1] = sin(lon_new[pix] *
M_PI / 180) * cos(lat_new[pix] *
M_PI / 180);
2159 bvec[2] = sin(lat_new[pix] *
M_PI / 180);
2162 if(last_dotprod < 0)
2163 last_dotprod = 0 - last_dotprod;
2164 double min_dotprod = last_dotprod;
2165 int min_dotprod_index = last_dotprod_index;
2166 bool found_new =
false;
2169 for (
i = last_dotprod_index+1;
i < num_gridlines;
i++) {
2178 min_dotprod_index =
i;
2180 last_dotprod_index =
i;
2185 if(!found_new && last_dotprod_index > 0) {
2186 for (
i = last_dotprod_index-1;
i >= 0;
i--) {
2194 min_dotprod_index =
i;
2196 last_dotprod_index =
i;
2201 if (min_dotprod <= db_fudge) {
2202 gdindex[pix][0] = min_dotprod_index + 1;
2212 if (dot_firstline <= db && dot_lastline > -
db) {
2214 irow = gdindex[pix][0] - 1;
2217 if (binl1c->
verbose)cout <<
"ERROR irow<0 in search_l1c..." << irow <<
"at pix#.." << pix + 1 << endl;
2222 for (
int j = 0;
j < nbinx;
j++) {
2227 gvec[2] = sin(binl1c->
lat_gd[irow][
j] *
M_PI / 180);
2229 c1 = bvec[0] - gvec[0];
2230 c2 = bvec[1] - gvec[1];
2231 c3 = bvec[2] - gvec[2];
2233 bmcm = sqrt(c1 * c1 + c2 * c2 + c3 * c3);
2242 cout <<
"ERROR col<1 in search_l1c..." << col <<
"at pix#.." << pix + 1 << endl;
2246 gdindex[pix][1] = col;
2248 if (irow == num_gridlines - 1 && lat_new[pix] < 85.0) {
2249 gdindex[pix][0] = -1;
2250 gdindex[pix][1] = -1;
2256 gdindex[pix][0] = -1;
2257 gdindex[pix][1] = -1;
2261 for (pix = 0; pix < num_pixels; pix++) {
2262 if (gdindex[pix][0] < 1 && gdindex[pix][1] < 1) {
2267 if (badpix == num_pixels) {
2272 if (binl1c->
verbose && flag_out == 110)
2273 cout <<
"THIS LINE WILL BE SKIPPED -- NO PIXELS BINNED.............." << endl;
2342 int32_t num_gridlines, nbinx;
2343 float gvec[3], bvec[3];
2349 int irow = -1, col = -1;
2350 float bmcm, bm = 100;
2353 double dotprod, dot_firstline, dot_lastline;
2355 int32_t last_dotprod_index = 0;
2356 double last_dotprod;
2359 nbinx = binl1c->
nbinx;
2360 num_pixels =
l1file->npix;
2362 db = (5.2) / 6371 / 2;
2363 double db_fudge =
db * 1.5;
2367 for (pix = 0; pix < num_pixels; pix++) {
2368 gdindex[pix][0] = -1;
2369 gdindex[pix][1] = -1;
2372 if (
l1rec->lat[pix] > 90 ||
l1rec->lat[pix] < -90 ||
l1rec->lon[pix] < -180 ||
2376 <<
"ERROR in search_l1cgen --latitude longitude pixel out of the boundaries.OR FILLVALUE."
2377 <<
"latpix>90 or <-90.." <<
l1rec->lat[pix] <<
"lonpix>180 or <-180.." <<
l1rec->lon[pix]
2386 bvec[2] = sin(
l1rec->lat[pix] *
M_PI / 180);
2389 if(last_dotprod < 0)
2390 last_dotprod = 0 - last_dotprod;
2391 double min_dotprod = last_dotprod;
2392 int min_dotprod_index = last_dotprod_index;
2393 bool found_new =
false;
2396 for (
i = last_dotprod_index+1;
i < num_gridlines;
i++) {
2405 min_dotprod_index =
i;
2407 last_dotprod_index =
i;
2412 if(!found_new && last_dotprod_index > 0) {
2413 for (
i = last_dotprod_index-1;
i >= 0;
i--) {
2421 min_dotprod_index =
i;
2423 last_dotprod_index =
i;
2428 if (min_dotprod <= db_fudge) {
2429 gdindex[pix][0] = min_dotprod_index + 1;
2439 if (dot_firstline <= db && dot_lastline > -
db) {
2441 irow = gdindex[pix][0] - 1;
2445 cout <<
"ERROR irow<0 in search_l1c..." << irow <<
"at pix#.." << pix + 1 << endl;
2450 for (
int j = 0;
j < nbinx;
j++) {
2455 gvec[2] = sin(binl1c->
lat_gd[irow][
j] *
M_PI / 180);
2457 c1 = bvec[0] - gvec[0];
2458 c2 = bvec[1] - gvec[1];
2459 c3 = bvec[2] - gvec[2];
2461 bmcm = sqrt(c1 * c1 + c2 * c2 + c3 * c3);
2470 cout <<
"ERROR col<1 in search_l1c..." << col <<
"at pix#.." << pix + 1 << endl;
2474 gdindex[pix][1] = col;
2476 if (irow == num_gridlines - 1 &&
l1rec->lat[pix] < 85.0) {
2477 gdindex[pix][0] = -1;
2478 gdindex[pix][1] = -1;
2484 gdindex[pix][0] = -1;
2485 gdindex[pix][1] = -1;
2489 for (pix = 0; pix < num_pixels; pix++) {
2490 if (gdindex[pix][0] < 1 && gdindex[pix][1] < 1) {
2495 if (badpix == num_pixels) {
2500 if (binl1c->
verbose && flag_out == 110)
2501 cout <<
"THIS LINE WILL BE SKIPPED -- NO PIXELS BINNED.............." << endl;
2508 int search2_l1c(
size_t ybins,
size_t xbins,
float lat,
float lon,
float **lat_gd,
float **lon_gd,
short *row,
2510 int32_t num_gridlines, nbinx, ic;
2511 short gdrow = -1, gdcol = -1;
2512 float pvec[3], gnvm,
db, pdotgn_first, pdotgn_last;
2513 float **gnvec =
nullptr, **cnvec =
nullptr, **dc =
nullptr;
2519 num_gridlines = ybins;
2522 db = (5.2) / 6371 / 2;
2531 for (
i = 0;
i < num_gridlines;
i++) {
2533 if (lat_gd[
i][nbinx - 1] > 90 || lat_gd[
i][nbinx - 1] < -90 || lon_gd[
i][nbinx - 1] < -180 ||
2534 lon_gd[
i][nbinx - 1] > 180) {
2538 if (lat_gd[
i][0] > 90 || lat_gd[
i][0] < -90 || lon_gd[
i][0] < -180 || lon_gd[
i][0] > 180) {
2543 gnvec[0][
i] = sin(lon_gd[
i][nbinx - 1] *
M_PI / 180) * cos(lat_gd[
i][nbinx - 1] *
M_PI / 180) *
2544 sin(lat_gd[
i][0] *
M_PI / 180) -
2545 sin(lat_gd[
i][nbinx - 1] *
M_PI / 180) * sin(lon_gd[
i][0] *
M_PI / 180) *
2546 cos(lat_gd[
i][0] *
M_PI / 180);
2547 gnvec[1][
i] = sin(lat_gd[
i][nbinx - 1] *
M_PI / 180) * cos(lon_gd[
i][0] *
M_PI / 180) *
2548 cos(lat_gd[
i][0] *
M_PI / 180) -
2549 cos(lon_gd[
i][nbinx - 1] *
M_PI / 180) * cos(lat_gd[
i][nbinx - 1] *
M_PI / 180) *
2550 sin(lat_gd[
i][0] *
M_PI / 180);
2551 gnvec[2][
i] = cos(lon_gd[
i][nbinx - 1] *
M_PI / 180) * cos(lat_gd[
i][nbinx - 1] *
M_PI / 180) *
2552 sin(lon_gd[
i][0] *
M_PI / 180) * cos(lat_gd[
i][0] *
M_PI / 180) -
2553 sin(lon_gd[
i][nbinx - 1] *
M_PI / 180) * cos(lat_gd[
i][nbinx - 1] *
M_PI / 180) *
2554 cos(lon_gd[
i][0] *
M_PI / 180) * cos(lat_gd[
i][0] *
M_PI / 180);
2556 gnvm = sqrt(gnvec[0][
i] * gnvec[0][
i] + gnvec[1][
i] * gnvec[1][
i] + gnvec[2][
i] * gnvec[2][
i]);
2557 if (isnan(gnvm) == 1) {
2566 gnvec[0][
i] = gnvec[0][
i] / gnvm;
2567 gnvec[1][
i] = gnvec[1][
i] / gnvm;
2568 gnvec[2][
i] = gnvec[2][
i] / gnvm;
2571 cnvec[0][
i] = sin(lon_gd[
i][ic] *
M_PI / 180) * cos(lat_gd[
i][ic] *
M_PI / 180) * gnvec[2][
i] -
2572 sin(lat_gd[
i][ic] *
M_PI / 180) * gnvec[1][
i];
2573 cnvec[1][
i] = sin(lat_gd[
i][ic] *
M_PI / 180) * gnvec[0][
i] -
2574 cos(lon_gd[
i][ic] *
M_PI / 180) * cos(lat_gd[
i][ic] *
M_PI / 180) * gnvec[2][
i];
2575 cnvec[2][
i] = cos(lon_gd[
i][ic] *
M_PI / 180) * cos(lat_gd[
i][ic] *
M_PI / 180) * gnvec[1][
i] -
2576 sin(lon_gd[
i][ic] *
M_PI / 180) * cos(lat_gd[
i][ic] *
M_PI / 180) * gnvec[0][
i];
2579 dc[0][
i] = cos(lon_gd[
i][ic + 1] *
M_PI / 180) * cos(lat_gd[
i][ic + 1] *
M_PI / 180) -
2580 cos(lon_gd[
i][ic] *
M_PI / 180) * cos(lat_gd[
i][ic] *
M_PI / 180);
2581 dc[1][
i] = sin(lon_gd[
i][ic + 1] *
M_PI / 180) * cos(lat_gd[
i][ic + 1] *
M_PI / 180) -
2582 sin(lon_gd[
i][ic] *
M_PI / 180) * cos(lat_gd[
i][ic] *
M_PI / 180);
2583 dc[2][
i] = sin(lat_gd[
i][ic + 1] *
M_PI / 180) - sin(lat_gd[
i][ic] *
M_PI / 180);
2588 for (
i = 0;
i < num_gridlines;
i++) {
2589 if (
lat > 90 ||
lat < -90 || lon < -180 || lon > 180) {
2596 pvec[2] = sin(
lat *
M_PI / 180);
2598 dotprod = pvec[0] * gnvec[0][
i] + pvec[1] * gnvec[1][
i] + pvec[2] * gnvec[2][
i];
2603 if (
i == num_gridlines - 1) {
2607 if (pdotgn_first <= db && pdotgn_last > -
db && gdrow < 0 && gdcol < 0) {
2612 if (dotprod <= db && dotprod > -
db && gdrow < 0) {
2617 dotprod2 = pvec[0] * cnvec[0][gdrow] + pvec[1] * cnvec[1][gdrow] + pvec[2] * cnvec[2][gdrow];
2619 sqrt(dc[0][gdrow] * dc[0][gdrow] + dc[1][gdrow] * dc[1][gdrow] + dc[2][gdrow] * dc[2][gdrow]);
2620 gdcol = ic + dotprod2 / dcm + .5;
2621 if (gdrow >= 0 && gdcol >= 0) {
2637 if (gnvec !=
nullptr)
2639 if (cnvec !=
nullptr)
2651 double cosunz = cos(
solz *
M_PI / 180.);
2652 double cosenz = cos(
senz *
M_PI / 180.);
2653 double term1 = -1 * cosunz + cosenz * cos(
senz *
M_PI / 180. +
M_PI / 180.);
2654 double cos2 = 0.5 * (cos(2 *
senz *
M_PI / 180.) + 1);
2658 if ((
sena - suna) < 2 * 180. && (
sena - suna) > 180.)
2659 term2 = sqrt(1 - cos2) * term3;
2660 if ((
sena - suna) < 180. && (
sena - suna) > 0.)
2661 term2 = -1 * sqrt(1 - cos2) * term3;
2663 double cos_alpha = term1 / term2;
2665 rotangle = acos(cos_alpha) * 180. /
M_PI;