/*************************************************************************** * Copyright (C) 2005 by Nicolas PASCAL * * nicolas.pascal@icare.univ-lille1.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "caliopfiledata.h" const float CALIOPFileData::colocation_tolerance=0.01; const float32 CALIOPFileData::meteo_level_altitude[]={39.855, 38.055, 35.955, 33.855, 32.055, 30.015, 28.035, 26.055, 24.075, 21.915, 19.995, 19.035, 18.015, 16.995, 15.975, 15.015, 13.995, 12.975, 12.015, 10.995, 9.975, 9.015, 8.01, 6.99, 6.0, 5.01, 3.99, 3.0, 2.01, 0.99, 0.0, -0.945, -1.845}; const float32 CALIOPFileData::cal_lid_l2_vfm_altitude[] = { -0.485, -0.455, -0.425, -0.395, -0.365, -0.335, -0.305, -0.275, -0.245, -0.215, -0.185, -0.155, -0.125, -0.095, -0.065, -0.035, -0.005, 0.025, 0.055, 0.085, 0.115, 0.145, 0.175, 0.205, 0.235, 0.265, 0.295, 0.325, 0.355, 0.385, 0.415, 0.445, 0.475, 0.505, 0.535, 0.565, 0.595, 0.625, 0.655, 0.685, 0.715, 0.745, 0.775, 0.805, 0.835, 0.865, 0.895, 0.925, 0.955, 0.985, 1.015, 1.045, 1.075, 1.105, 1.135, 1.165, 1.195, 1.225, 1.255, 1.285, 1.315, 1.345, 1.375, 1.405, 1.435, 1.465, 1.495, 1.525, 1.555, 1.585, 1.615, 1.645, 1.675, 1.705, 1.735, 1.765, 1.795, 1.825, 1.855, 1.885, 1.915, 1.945, 1.975, 2.005, 2.035, 2.065, 2.095, 2.125, 2.155, 2.185, 2.215, 2.245, 2.275, 2.305, 2.335, 2.365, 2.395, 2.425, 2.455, 2.485, 2.515, 2.545, 2.575, 2.605, 2.635, 2.665, 2.695, 2.725, 2.755, 2.785, 2.815, 2.845, 2.875, 2.905, 2.935, 2.965, 2.995, 3.025, 3.055, 3.085, 3.115, 3.145, 3.175, 3.205, 3.235, 3.265, 3.295, 3.325, 3.355, 3.385, 3.415, 3.445, 3.475, 3.505, 3.535, 3.565, 3.595, 3.625, 3.655, 3.685, 3.715, 3.745, 3.775, 3.805, 3.835, 3.865, 3.895, 3.925, 3.955, 3.985, 4.015, 4.045, 4.075, 4.105, 4.135, 4.165, 4.195, 4.225, 4.255, 4.285, 4.315, 4.345, 4.375, 4.405, 4.435, 4.465, 4.495, 4.525, 4.555, 4.585, 4.615, 4.645, 4.675, 4.705, 4.735, 4.765, 4.795, 4.825, 4.855, 4.885, 4.915, 4.945, 4.975, 5.005, 5.035, 5.065, 5.095, 5.125, 5.155, 5.185, 5.215, 5.245, 5.275, 5.305, 5.335, 5.365, 5.395, 5.425, 5.455, 5.485, 5.515, 5.545, 5.575, 5.605, 5.635, 5.665, 5.695, 5.725, 5.755, 5.785, 5.815, 5.845, 5.875, 5.905, 5.935, 5.965, 5.995, 6.025, 6.055, 6.085, 6.115, 6.145, 6.175, 6.205, 6.235, 6.265, 6.295, 6.325, 6.355, 6.385, 6.415, 6.445, 6.475, 6.505, 6.535, 6.565, 6.595, 6.625, 6.655, 6.685, 6.715, 6.745, 6.775, 6.805, 6.835, 6.865, 6.895, 6.925, 6.955, 6.985, 7.015, 7.045, 7.075, 7.105, 7.135, 7.165, 7.195, 7.225, 7.255, 7.285, 7.315, 7.345, 7.375, 7.405, 7.435, 7.465, 7.495, 7.525, 7.555, 7.585, 7.615, 7.645, 7.675, 7.705, 7.735, 7.765, 7.795, 7.825, 7.855, 7.885, 7.915, 7.945, 7.975, 8.005, 8.035, 8.065, 8.095, 8.125, 8.155, 8.185, 8.230, 8.290, 8.350, 8.410, 8.470, 8.530, 8.590, 8.650, 8.710, 8.770, 8.830, 8.890, 8.950, 9.010, 9.070, 9.130, 9.190, 9.250, 9.310, 9.370, 9.430, 9.490, 9.550, 9.610, 9.670, 9.730, 9.790, 9.850, 9.910, 9.970, 10.030, 10.090, 10.150, 10.210, 10.270, 10.330, 10.390, 10.450, 10.510, 10.570, 10.630, 10.690, 10.750, 10.810, 10.870, 10.930, 10.990, 11.050, 11.110, 11.170, 11.230, 11.290, 11.350, 11.410, 11.470, 11.530, 11.590, 11.650, 11.710, 11.770, 11.830, 11.890, 11.950, 12.010, 12.070, 12.130, 12.190, 12.250, 12.310, 12.370, 12.430, 12.490, 12.550, 12.610, 12.670, 12.730, 12.790, 12.850, 12.910, 12.970, 13.030, 13.090, 13.150, 13.210, 13.270, 13.330, 13.390, 13.450, 13.510, 13.570, 13.630, 13.690, 13.750, 13.810, 13.870, 13.930, 13.990, 14.050, 14.110, 14.170, 14.230, 14.290, 14.350, 14.410, 14.470, 14.530, 14.590, 14.650, 14.710, 14.770, 14.830, 14.890, 14.950, 15.010, 15.070, 15.130, 15.190, 15.250, 15.310, 15.370, 15.430, 15.490, 15.550, 15.610, 15.670, 15.730, 15.790, 15.850, 15.910, 15.970, 16.030, 16.090, 16.150, 16.210, 16.270, 16.330, 16.390, 16.450, 16.510, 16.570, 16.630, 16.690, 16.750, 16.810, 16.870, 16.930, 16.990, 17.050, 17.110, 17.170, 17.230, 17.290, 17.350, 17.410, 17.470, 17.530, 17.590, 17.650, 17.710, 17.770, 17.830, 17.890, 17.950, 18.010, 18.070, 18.130, 18.190, 18.250, 18.310, 18.370, 18.430, 18.490, 18.550, 18.610, 18.670, 18.730, 18.790, 18.850, 18.910, 18.970, 19.030, 19.090, 19.150, 19.210, 19.270, 19.330, 19.390, 19.450, 19.510, 19.570, 19.630, 19.690, 19.750, 19.810, 19.870, 19.930, 19.990, 20.050, 20.110, 20.170, 20.290, 20.470, 20.650, 20.830, 21.010, 21.190, 21.370, 21.550, 21.730, 21.910, 22.090, 22.270, 22.450, 22.630, 22.810, 22.990, 23.170, 23.350, 23.530, 23.710, 23.890, 24.070, 24.250, 24.430, 24.610, 24.790, 24.970, 25.150, 25.330, 25.510, 25.690, 25.870, 26.050, 26.230, 26.410, 26.590, 26.770, 26.950, 27.130, 27.310, 27.490, 27.670, 27.850, 28.030, 28.210, 28.390, 28.570, 28.750, 28.930, 29.110, 29.290, 29.470, 29.650, 29.830, 30.010 }; const float32 CALIOPFileData::cal_lid_l2_vfm_altitude_ud[] = { 30.010, 29.830, 29.650, 29.470, 29.290, 29.110, 28.930, 28.750, 28.570, 28.390, 28.210, 28.030, 27.850, 27.670, 27.490, 27.310, 27.130, 26.950, 26.770, 26.590, 26.410, 26.230, 26.050, 25.870, 25.690, 25.510, 25.330, 25.150, 24.970, 24.790, 24.610, 24.430, 24.250, 24.070, 23.890, 23.710, 23.530, 23.350, 23.170, 22.990, 22.810, 22.630, 22.450, 22.270, 22.090, 21.910, 21.730, 21.550, 21.370, 21.190, 21.010, 20.830, 20.650, 20.470, 20.290, 20.170, 20.110, 20.050, 19.990, 19.930, 19.870, 19.810, 19.750, 19.690, 19.630, 19.570, 19.510, 19.450, 19.390, 19.330, 19.270, 19.210, 19.150, 19.090, 19.030, 18.970, 18.910, 18.850, 18.790, 18.730, 18.670, 18.610, 18.550, 18.490, 18.430, 18.370, 18.310, 18.250, 18.190, 18.130, 18.070, 18.010, 17.950, 17.890, 17.830, 17.770, 17.710, 17.650, 17.590, 17.530, 17.470, 17.410, 17.350, 17.290, 17.230, 17.170, 17.110, 17.050, 16.990, 16.930, 16.870, 16.810, 16.750, 16.690, 16.630, 16.570, 16.510, 16.450, 16.390, 16.330, 16.270, 16.210, 16.150, 16.090, 16.030, 15.970, 15.910, 15.850, 15.790, 15.730, 15.670, 15.610, 15.550, 15.490, 15.430, 15.370, 15.310, 15.250, 15.190, 15.130, 15.070, 15.010, 14.950, 14.890, 14.830, 14.770, 14.710, 14.650, 14.590, 14.530, 14.470, 14.410, 14.350, 14.290, 14.230, 14.170, 14.110, 14.050, 13.990, 13.930, 13.870, 13.810, 13.750, 13.690, 13.630, 13.570, 13.510, 13.450, 13.390, 13.330, 13.270, 13.210, 13.150, 13.090, 13.030, 12.970, 12.910, 12.850, 12.790, 12.730, 12.670, 12.610, 12.550, 12.490, 12.430, 12.370, 12.310, 12.250, 12.190, 12.130, 12.070, 12.010, 11.950, 11.890, 11.830, 11.770, 11.710, 11.650, 11.590, 11.530, 11.470, 11.410, 11.350, 11.290, 11.230, 11.170, 11.110, 11.050, 10.990, 10.930, 10.870, 10.810, 10.750, 10.690, 10.630, 10.570, 10.510, 10.450, 10.390, 10.330, 10.270, 10.210, 10.150, 10.090, 10.030, 9.970, 9.910, 9.850, 9.790, 9.730, 9.670, 9.610, 9.550, 9.490, 9.430, 9.370, 9.310, 9.250, 9.190, 9.130, 9.070, 9.010, 8.950, 8.890, 8.830, 8.770, 8.710, 8.650, 8.590, 8.530, 8.470, 8.410, 8.350, 8.290, 8.230, 8.185, 8.155, 8.125, 8.095, 8.065, 8.035, 8.005, 7.975, 7.945, 7.915, 7.885, 7.855, 7.825, 7.795, 7.765, 7.735, 7.705, 7.675, 7.645, 7.615, 7.585, 7.555, 7.525, 7.495, 7.465, 7.435, 7.405, 7.375, 7.345, 7.315, 7.285, 7.255, 7.225, 7.195, 7.165, 7.135, 7.105, 7.075, 7.045, 7.015, 6.985, 6.955, 6.925, 6.895, 6.865, 6.835, 6.805, 6.775, 6.745, 6.715, 6.685, 6.655, 6.625, 6.595, 6.565, 6.535, 6.505, 6.475, 6.445, 6.415, 6.385, 6.355, 6.325, 6.295, 6.265, 6.235, 6.205, 6.175, 6.145, 6.115, 6.085, 6.055, 6.025, 5.995, 5.965, 5.935, 5.905, 5.875, 5.845, 5.815, 5.785, 5.755, 5.725, 5.695, 5.665, 5.635, 5.605, 5.575, 5.545, 5.515, 5.485, 5.455, 5.425, 5.395, 5.365, 5.335, 5.305, 5.275, 5.245, 5.215, 5.185, 5.155, 5.125, 5.095, 5.065, 5.035, 5.005, 4.975, 4.945, 4.915, 4.885, 4.855, 4.825, 4.795, 4.765, 4.735, 4.705, 4.675, 4.645, 4.615, 4.585, 4.555, 4.525, 4.495, 4.465, 4.435, 4.405, 4.375, 4.345, 4.315, 4.285, 4.255, 4.225, 4.195, 4.165, 4.135, 4.105, 4.075, 4.045, 4.015, 3.985, 3.955, 3.925, 3.895, 3.865, 3.835, 3.805, 3.775, 3.745, 3.715, 3.685, 3.655, 3.625, 3.595, 3.565, 3.535, 3.505, 3.475, 3.445, 3.415, 3.385, 3.355, 3.325, 3.295, 3.265, 3.235, 3.205, 3.175, 3.145, 3.115, 3.085, 3.055, 3.025, 2.995, 2.965, 2.935, 2.905, 2.875, 2.845, 2.815, 2.785, 2.755, 2.725, 2.695, 2.665, 2.635, 2.605, 2.575, 2.545, 2.515, 2.485, 2.455, 2.425, 2.395, 2.365, 2.335, 2.305, 2.275, 2.245, 2.215, 2.185, 2.155, 2.125, 2.095, 2.065, 2.035, 2.005, 1.975, 1.945, 1.915, 1.885, 1.855, 1.825, 1.795, 1.765, 1.735, 1.705, 1.675, 1.645, 1.615, 1.585, 1.555, 1.525, 1.495, 1.465, 1.435, 1.405, 1.375, 1.345, 1.315, 1.285, 1.255, 1.225, 1.195, 1.165, 1.135, 1.105, 1.075, 1.045, 1.015, 0.985, 0.955, 0.925, 0.895, 0.865, 0.835, 0.805, 0.775, 0.745, 0.715, 0.685, 0.655, 0.625, 0.595, 0.565, 0.535, 0.505, 0.475, 0.445, 0.415, 0.385, 0.355, 0.325, 0.295, 0.265, 0.235, 0.205, 0.175, 0.145, 0.115, 0.085, 0.055, 0.025, -0.005, -0.035, -0.065, -0.095, -0.125, -0.155, -0.185, -0.215, -0.245, -0.275, -0.305, -0.335, -0.365, -0.395, -0.425, -0.455, -0.485 }; const float32 CALIOPFileData::cal_lid_l2_05kmCPro_altitude[] = { 20.156235, 20.09636, 20.036482, 19.976606, 19.916729, 19.856853, 19.796978, 19.7371, 19.677225, 19.617348, 19.557472, 19.497595, 19.43772, 19.377844, 19.317966, 19.258091, 19.198214, 19.138338, 19.07846, 19.018585, 18.958708, 18.898832, 18.838957, 18.77908, 18.719204, 18.659327, 18.599451, 18.539574, 18.479698, 18.419823, 18.359945, 18.30007, 18.240192, 18.180317, 18.12044, 18.060564, 18.000687, 17.940811, 17.880936, 17.821058, 17.761183, 17.701305, 17.64143, 17.581553, 17.521677, 17.461802, 17.401924, 17.342049, 17.282171, 17.222296, 17.162418, 17.102543, 17.042667, 16.98279, 16.922915, 16.863037, 16.803162, 16.743284, 16.683409, 16.623531, 16.563656, 16.50378, 16.443903, 16.384027, 16.32415, 16.264275, 16.204397, 16.144522, 16.084646, 16.024769, 15.964892, 15.905016, 15.84514, 15.785264, 15.725388, 15.665511, 15.605635, 15.545758, 15.485882, 15.426005, 15.36613, 15.306253, 15.246377, 15.186501, 15.126624, 15.066748, 15.006871, 14.946995, 14.887119, 14.827243, 14.767366, 14.70749, 14.647614, 14.587737, 14.527861, 14.467984, 14.408109, 14.348232, 14.288356, 14.228479, 14.168603, 14.1087265, 14.04885, 13.988974, 13.929098, 13.869222, 13.809345, 13.749469, 13.689592, 13.629716, 13.5698395, 13.509963, 13.450088, 13.390211, 13.330335, 13.270458, 13.210582, 13.150705, 13.090829, 13.030952, 12.971077, 12.911201, 12.851324, 12.791448, 12.731571, 12.671695, 12.611818, 12.551942, 12.492066, 12.43219, 12.3723135, 12.312437, 12.252561, 12.192684, 12.132808, 12.072931, 12.013056, 11.953179, 11.893303, 11.833426, 11.77355, 11.713674, 11.653797, 11.593921, 11.534045, 11.474169, 11.414292, 11.354416, 11.294539, 11.234663, 11.174787, 11.114911, 11.055035, 10.995158, 10.935282, 10.875405, 10.815529, 10.755652, 10.695776, 10.6359005, 10.576024, 10.516148, 10.456271, 10.396395, 10.336518, 10.276642, 10.216765, 10.15689, 10.097013, 10.037137, 9.977261, 9.917384, 9.857508, 9.797631, 9.737755, 9.677879, 9.618003, 9.558126, 9.49825, 9.438374, 9.378497, 9.318621, 9.258744, 9.198869, 9.138992, 9.079116, 9.019239, 8.959363, 8.899487, 8.83961, 8.779734, 8.719858, 8.659982, 8.600105, 8.540229, 8.480352, 8.420476, 8.3605995, 8.300723, 8.240848, 8.180971, 8.121095, 8.061218, 8.001342, 7.9414654, 7.881589, 7.8217125, 7.761837, 7.7019606, 7.642084, 7.5822077, 7.522331, 7.462455, 7.4025784, 7.3427024, 7.2828264, 7.22295, 7.1630735, 7.103197, 7.0433207, 6.983444, 6.923568, 6.863692, 6.803816, 6.7439394, 6.684063, 6.6241865, 6.56431, 6.5044336, 6.444557, 6.384681, 6.3248053, 6.264929, 6.2050524, 6.145176, 6.0852995, 6.025423, 5.9655466, 5.9056706, 5.8457947, 5.785918, 5.726042, 5.6661654, 5.606289, 5.5464125, 5.486536, 5.42666, 5.366784, 5.3069077, 5.247031, 5.187155, 5.1272783, 5.067402, 5.0075254, 4.9476495, 4.8877735, 4.827897, 4.7680206, 4.708144, 4.6482677, 4.5883913, 4.528515, 4.4686394, 4.408763, 4.3488865, 4.28901, 4.2291336, 4.169257, 4.1093807, 4.0495043, 3.9896283, 3.929752, 3.8698757, 3.8099995, 3.750123, 3.6902468, 3.6303704, 3.5704942, 3.5106177, 3.4507415, 3.390865, 3.330989, 3.2711124, 3.2112362, 3.1513598, 3.0914836, 3.0316072, 2.971731, 2.9118545, 2.8519783, 2.7921019, 2.7322257, 2.6723492, 2.612473, 2.5525966, 2.4927204, 2.432844, 2.3729677, 2.3130913, 2.253215, 2.1933386, 2.1334624, 2.073586, 2.0137098, 1.9538333, 1.8939571, 1.8340807, 1.7742045, 1.7143282, 1.6544518, 1.5945755, 1.5346992, 1.4748229, 1.4149466, 1.3550702, 1.2951939, 1.2353176, 1.1754413, 1.115565, 1.0556886, 0.9958123, 0.935936, 0.87605965, 0.8161833, 0.756307, 0.6964307, 0.63655436, 0.57667804, 0.5168017, 0.4569254, 0.39704907, 0.33717275, 0.27729642, 0.2174201, 0.15754378, 0.09766746, 0.03779114, -0.022085179, -0.0819615, -0.14183782, -0.20171414, -0.26159048, -0.32146677, -0.3813431, -0.44121942 }; CALIOPFileData::CALIOPFileData(const string &name /*= ""*/, const string &mode/*= "r"*/) : FileData(name,mode),SatelliteFileData(name,mode),HDFFileData(name,mode) { init(); } void CALIOPFileData::init() { product_type=CAL_LID_UNDEFINED; product = ""; v_pos_data = NULL; v_alt_data = NULL; // extract the acquisition date from the file name string short_filename = get_tail(get_name()); parse_filename(short_filename); load_hdf_file(); load_hdf_metadata(); // metadata->view_tree(); set_lat_lon_index_max(); set_time_coverage(); free_hdf_metadata(); free_hdf_file(); } CALIOPFileData::~CALIOPFileData() { free_hdf_file(); free_hdf_metadata(); free_geolocation_data(); } void CALIOPFileData::set_time_coverage() { bool already_loaded_metadata = is_hdf_metadata_loaded(); if (!already_loaded_metadata) load_hdf_metadata(); // read start and stop acquisition time in the metadata string s_time_start(""); string s_time_end(""); metadata->get_value( (void*) (&s_time_start), "START_DATE"); metadata->get_value( (void*) (&s_time_end), "STOP_DATE"); // compute number of seconds between stop and start acquisition time Date date_start; date_start.set_date_str( s_time_start.substr(0,19), "%Y-%m-%eT%H:%M:%S" ); Date date_end; date_end.set_date_str ( s_time_end.substr(0,19), "%Y-%m-%eT%H:%M:%S" ); time_coverage = date_end.get_epoch_time() - date_start.get_epoch_time(); if (!already_loaded_metadata) free_hdf_metadata(); } void CALIOPFileData::set_lat_lon_index_max() { bool is_hdf_file_already_loaded=is_hdf_file_loaded(); if (!is_hdf_file_already_loaded) load_hdf_file(); Hdf_file * hdf = get_hdf_file(); if (hdf!=NULL) { lat_lon_index_max[0] = hdf->get_sds(latitude_sds_name.c_str()).get_dimension(0)-1; lat_lon_index_max[1] = hdf->get_sds(latitude_sds_name.c_str()).get_dimension(1)-1; } if (!is_hdf_file_already_loaded) free_hdf_file(); } const bool CALIOPFileData::is_day() const { return day_mode; } void CALIOPFileData::check_filename( const string& short_filename ) const { int first_minus_pos = short_filename.find_first_of("-"); // check the extension string extension=short_filename.substr(short_filename.size()-4,4); if (extension!=".hdf") { invalid_filename e(__FILE__,__LINE__,short_filename,"CALIOP"); throw e; } // check the product radix string radix=short_filename.substr(0,first_minus_pos); if (radix!="CAL_LID_L1" && radix!="CAL_LID_L2_333mCLay" && radix!="CAL_LID_L2_01kmCLay" && radix!="CAL_LID_L2_05kmCLay" && radix!="CAL_LID_L2_05kmALay" && radix!="CAL_LID_L2_40kmAProCal" && radix!="CAL_LID_L2_VFM" && radix!="CAL_LID_L2_05kmCPro" ) { invalid_filename e(__FILE__,__LINE__,short_filename,"CALIOP"); throw e; } // check the day/night flag char day_mode=short_filename[short_filename.size()-5]; if (day_mode!='D' && day_mode!='N') { invalid_filename e(__FILE__,__LINE__,short_filename,"CALIOP"); throw e; } } void CALIOPFileData::parse_filename( const string& short_filename ) { //--- check the validity of the filename check_filename(short_filename); //--- set the product type/resolution/level using the product radix int first_minus_pos = short_filename.find_first_of("-"); string radix=short_filename.substr(0,first_minus_pos); // default : only different for CAL_40kmAPro products latitude_sds_name = "Latitude"; longitude_sds_name = "Longitude"; time_sds_name = "Profile_Time"; if (radix=="CAL_LID_L1") { resolution=.333; level=1; nb_layer=nb_vbins; product_type=CAL_LID_L1; } else if (radix=="CAL_LID_L2_333mCLay") { resolution=.333; level=2; nb_layer=nb_cloud_layer; product_type=CAL_LID_L2_333mCLay; } else if (radix=="CAL_LID_L2_01kmCLay") { resolution=1.; level=2; nb_layer=nb_cloud_layer; product_type=CAL_LID_L2_01kmCLay; } else if (radix=="CAL_LID_L2_05kmCLay") { resolution=5.; level=2; nb_layer=nb_cloud_layer; product_type=CAL_LID_L2_05kmCLay; } else if (radix=="CAL_LID_L2_05kmALay") { resolution=5.; level=2; nb_layer=nb_aerosol_layer; product_type=CAL_LID_L2_05kmALay; } else if (radix=="CAL_LID_L2_40kmAProCal") { resolution=40.; level=2; product_type=CAL_LID_L2_40kmAPro; latitude_sds_name="Latitude_Start"; longitude_sds_name="Longitude_Start"; time_sds_name="Profile_Time_Start"; } else if (radix=="CAL_LID_L2_VFM") { resolution=333.; // convention : VFM products contains many resolution. Let's consider the better one level=2; nb_layer=nb_vfm_bins; product_type=CAL_LID_L2_VFM; } else if (radix=="CAL_LID_L2_05kmCPro") { resolution=5.; level=2; nb_layer=nb_05kmcpro_bins; product_type=CAL_LID_L2_05kmCPro; } else { // should never arrive here invalid_filename e(__FILE__,__LINE__,short_filename,"CALIOP"); throw e; } product = radix; // ---set the acquisition date string s_date = short_filename.substr(short_filename.size()-25,21); date->set_date_str(s_date,"%Y-%m-%eT%H-%M-%S"); // ---set the day/night mode char s_day_mode=short_filename[short_filename.size()-5]; if ( s_day_mode == 'D' ) day_mode=true; else if ( s_day_mode == 'N') day_mode=false; } const int CALIOPFileData::get_nb_geo_points() const { int ret = get_lat_lon_index_max()[0]+1; return ret; } /*********** CALIOP SPECIFIC ACCESS METHODS **********************/ void CALIOPFileData::set_lat_lon_min_max() { if (metadata != NULL) { // read the min max in the metadata float *val = new float; metadata->get_value(val,"MINLAT"); lat_min=*val; metadata->get_value(val,"MINLON"); lon_min=*val; metadata->get_value(val,"MAXLAT"); lat_max=*val; metadata->get_value(val,"MAXLON"); lon_max=*val; delete val; } else { // search the extremas "manually" in all the data bool data_already_loaded=is_geolocation_data_loaded(); if (!data_already_loaded) load_geolocation_data(); float min,max; uint nb_points = get_nb_geo_points(); float val; // Latitude min=1000.; max=-1000.; for ( uint i = 0 ; imax) max=val; } lat_min=min; lat_max=max; // Longitude min=1000.; max=-1000.; for ( uint i = 0 ; imax) max=val; } lon_min=min; lon_max=max; if (!data_already_loaded) free_geolocation_data(); } } const bool CALIOPFileData::is_geolocation_data_loaded() const { return (lat_data!=NULL && lon_data!=NULL && time_data!=NULL); } void CALIOPFileData::free_geolocation_data() { if (!is_geolocation_data_loaded()) { delete[] lat_data; lat_data=NULL; delete[] lon_data; lon_data=NULL; delete[] time_data; time_data=NULL; } } void CALIOPFileData::load_geolocation_data() { if ( ! is_geolocation_data_loaded() ) { // hdf_file is needed, but the method assume to conserve the caller's state bool hdf_file_already_loaded = is_hdf_file_loaded(); if (!hdf_file_already_loaded) load_hdf_file(); // name and structure of the (lat,lon,time) SDS to load depend of the products uint nb_points = get_nb_geo_points(); if ( product_type == CAL_LID_L1 || product_type == CAL_LID_L2_333mCLay || product_type == CAL_LID_L2_01kmCLay || product_type == CAL_LID_L2_VFM || product_type == CAL_LID_L2_05kmCPro ) { lat_data = static_cast( read_data( lat_data, latitude_sds_name.c_str() ) ); lon_data = static_cast( read_data( lon_data, longitude_sds_name.c_str() ) ); time_data = static_cast( read_data( time_data, time_sds_name.c_str() ) ); } else if ( product_type == CAL_LID_L2_05kmCLay || product_type == CAL_LID_L2_05kmALay ) { int start[] = {0,1}; int edges[] = {nb_points,1}; lat_data = static_cast( read_data( lat_data, latitude_sds_name.c_str(), start, NULL, edges ) ); lon_data = static_cast( read_data( lon_data, longitude_sds_name.c_str(), start, NULL, edges ) ); time_data = static_cast( read_data( time_data, time_sds_name.c_str(), start, NULL, edges ) ); } else if ( product_type == CAL_LID_L2_40kmAPro ) { float *lat_data1 = NULL; float *lat_data2 = NULL; float *lon_data1 = NULL; float *lon_data2 = NULL; double *time_data1 = NULL; double *time_data2 = NULL; // read lat, lon, time data lat_data1=static_cast(read_data((void*)lat_data1,"Latitude_Start")); lat_data2=static_cast(read_data((void*)lat_data2,"Latitude_Stop")); lon_data1=static_cast(read_data((void*)lon_data1,"Longitude_Start")); lon_data2=static_cast(read_data((void*)lon_data2,"Longitude_Stop")); time_data1=static_cast(read_data((void*)time_data1,"Profile_Time_Start")); time_data2=static_cast(read_data((void*)time_data2,"Profile_Time_Stop")); uint nb_points = get_nb_geo_points(); lat_data = new float[nb_points]; lon_data = new float[nb_points]; time_data = new double[nb_points]; for(uint i=0; i< nb_points; i++){ lat_data[i]=(lat_data1[i]+lat_data2[i])/2.0; lon_data[i]=(lon_data1[i]+lon_data2[i])/2.0; time_data[i]=(time_data1[i]+time_data2[i])/2.0; } delete[] lat_data1; delete[] lon_data1; delete[] time_data1; delete[] lat_data2; delete[] lon_data2; delete[] time_data2; } else { UnimplementedProduct e(__FILE__,__LINE__,__PRETTY_FUNCTION__); throw e; } load_v_pixel(); if (!hdf_file_already_loaded) free_hdf_file(); } } const float CALIOPFileData::get_nearest_point_distance( const float & lat, const float & lon, const float coloc_tolerance ) { bool data_already_loaded=is_geolocation_data_loaded(); if (!data_already_loaded) load_geolocation_data(); int nearest_point_idx; double nearest_point_distance=-1.; if (get_index(lat,lon,nearest_point_idx,coloc_tolerance)) // a point in the coincidence frame has been found nearest_point_distance=sqrt(pow(lat_data[nearest_point_idx]-lat,2) + pow(lon_data[nearest_point_idx]-lon,2)); if (!data_already_loaded) free_geolocation_data(); return nearest_point_distance; } const bool CALIOPFileData::contain_location(const float &lat,const float &lon, const double &tolerance){ int nearest_idx=-1; return get_index(lat,lon,nearest_idx,colocation_tolerance); } const bool CALIOPFileData::contain_data( const float & lat, const float & lon, const double & time, const double &colocation_tolerance ) { return contain_location(lat,lon,colocation_tolerance)&&contain_time(time); } const bool CALIOPFileData::get_index( const float &lat, const float & lon, int &index, const float coloc_tolerance) { index=-1; // index for no coincidence found // use coord float my_lon=lon; float my_lat=lat; bool data_already_loaded=is_geolocation_data_loaded(); if (!data_already_loaded) load_geolocation_data(); double delta_lat=9999.; // 9999 is bigger than the biggest delta that can be double delta_lon=9999.; double delta=9999.,best_delta=9999.; int nearest_index=-1; int end=get_nb_geo_points(); for (int i=0; i ipix(1); // index of a pixel for (int record_idx=0;record_idx > &v_index, const float & lat, const float & lon, const float colocation_tolerance) { // construct the pixel we are searching the coincidences vector val(1); val[0]=-1; PixelType pixel( &lat, &lon, val); // clean output vector v_index.clear(); // build pixels list vector < PixelType > v_neighbour(0); pixel.get_neighbours( v_neighbour, v_pixel, colocation_tolerance, true ); // build pixel indices list for ( vector < PixelType >::iterator i = v_neighbour.begin() ; i != v_neighbour.end() ; ++i ) v_index.push_back( i->get_val() ); // printf("Neighbours to (%f,%f) :\n",pixel.get_lat(),pixel.get_lon()); // for ( vector < PixelType >::iterator i = v_neighbour.begin() ; i != v_neighbour.end() ; ++i ) // printf("(%f,%f)\tidx=%d\tdist=%f\n",i->get_lat(),i->get_lon(), i->get_val()[0], pixel.distance(*i) ); // printf("\n"); } // void CALIOPFileData::load_viewing_directions() { // assert(is_geolocation_data_loaded()); // // // init container if needed // viewing_directions.clear(); // // // points representing the location of the viewed pixel and the satellite // Carthesian::Point3D p_sat; // Geocentric::Point3D p_view; // Carthesian::Segment3D view; // // vector ipix (1); // // // --- preload needed variables // // // satellite position // // float64 * v_pos = (float64 *)(read_data (NULL, "Spacecraft_Position")); // km // // // viewed pixel altitude // // string ds_name (""); // // switch (product_type) { // // case CAL_LID_L1: // // ds_name = "Surface_Elevation"; // // break; // // case CAL_LID_L2_333mCLay: // // case CAL_LID_L2_01kmCLay: // // case CAL_LID_L2_05kmCLay: // // case CAL_LID_L2_05kmALay: // // ds_name = "DEM_Surface_Elevation"; // // break; // // default: // // UnimplementedProduct e(__FILE__,__LINE__,__PRETTY_FUNCTION__); // // throw e; // // break; // // } // // float32 * v_alt = (float32 *)(read_data (NULL, ds_name.c_str())); // km // // fill value. Assumed to be the same for the 2 datasets // float32 fill_value_max = -9999. + 1.; // // // construct viewing segments // int nrec = get_dataset_dimension (ds_name)[0]; // float32 lat, lon, alt; // lat, lon, alt of earth observer position // double x, y, z; // x, y, z ECR carthesian coordinates of satellite // int ibuf = 0; // sat pos buffer indice // for (int irec = 0 ; irec < nrec ; ++irec) { // lat = lat_data[irec]; // lon = lon_data[irec]; // alt = v_alt[irec]; // x = v_pos [ibuf++]; // y = v_pos [ibuf++]; // z = v_pos [ibuf++]; // if ((lat < fill_value_max) || (lon < fill_value_max) || (alt < fill_value_max) || // (x < fill_value_max) || (y < fill_value_max) || (z < fill_value_max)) // // missing infos -> skip pixel // continue; // // unit conversion : km -> m // alt *= 1e3; // x *= 1e3; // y *= 1e3; // z *= 1e3; // // set viewing segment extremities // p_view.set (lat, lon, alt); // p_sat.set (x, y, z); // // construct and store viewing segment // view.set(p_view.to_carthesian(), p_sat); // ipix[0] = irec; // viewing_directions[ipix] = view; // } // } bool CALIOPFileData::is_viewing_directions_data_loaded() { return (v_alt_data != NULL); } void CALIOPFileData::load_viewing_directions_data() { // satellite position v_pos_data = (float64 *)(read_data (NULL, "Spacecraft_Position")); // km // viewed pixel altitude string ds_name (""); switch (product_type) { case CAL_LID_L1: ds_name = "Surface_Elevation"; break; case CAL_LID_L2_333mCLay: case CAL_LID_L2_01kmCLay: case CAL_LID_L2_05kmCLay: case CAL_LID_L2_05kmALay: ds_name = "DEM_Surface_Elevation"; break; default: UnimplementedProduct e(__FILE__,__LINE__,__PRETTY_FUNCTION__); throw e; break; } v_alt_data = (float32 *)(read_data (NULL, ds_name.c_str())); // km } void CALIOPFileData::free_viewing_directions_data() { delete [] v_pos_data, v_pos_data = NULL; delete [] v_alt_data, v_alt_data = NULL; } void CALIOPFileData::get_viewing_directions(const vector< int > & ipix, vector< Observation > & v_obs) { if (v_pos_data == NULL) { g_exception e(__FILE__ , __LINE__ , "Viewing directon data not loaded. Consider calling load_viewing_directions_data() before"); throw e; } // init container if needed v_obs.clear(); // record to read int irec = ipix[0]; // points representing the location of the viewed pixel and the satellite Carthesian::Point3D p_sat; Geodetic::Point3D p_view; Carthesian::Segment3D view; // fill value. Assumed to be the same for the 2 datasets float32 fill_value_max = -9999. + 1.; // construct viewing segments float32 lat, lon, alt; // lat, lon, alt of earth observer position lat = lat_data[irec]; lon = lon_data[irec]; alt = v_alt_data[irec]; float64 time = time_data[irec]; // TAI time of profile double x, y, z; // x, y, z ECR carthesian coordinates of satellite int ibuf = irec * 3; // sat pos buffer indice x = v_pos_data [ibuf++]; y = v_pos_data [ibuf++]; z = v_pos_data [ibuf++]; if ((lat > fill_value_max) && (lon > fill_value_max) && (alt > fill_value_max) && (x > fill_value_max) && (y > fill_value_max) && (z > fill_value_max)) { // unit conversion : km -> m alt *= 1e3; x *= 1e3; y *= 1e3; z *= 1e3; // set viewing segment extremities p_view.set (lat, lon, alt); p_sat.set (x, y, z); // construct and store viewing segment Carthesian::Segment3D viewing(p_sat, p_view.to_carthesian()); Observation obs(lat, lon, alt, time, ipix, ipix, viewing); v_obs.push_back (obs); } }