-
Notifications
You must be signed in to change notification settings - Fork 2
Lroc #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Lroc #46
Changes from all commits
39eedca
a55d044
d0a5f97
961204a
26023ec
8225480
d708761
e93a8d3
7bc927f
f17663b
ca89c61
a7c3566
0f3fb36
bdd97e4
582c69b
ccf8593
0b31673
ec71272
3e140cf
55b58bd
f9dfa1d
3e61969
46557fe
8e2b847
63575d7
4cebd20
41e1872
a98cf0e
0ab0e42
8e45709
75ac427
9e58d57
a95661c
1d7fe20
9b05d60
5343ed1
232ca0c
3acefbc
3eb7e83
6757e2f
b2df394
041f69f
18a7940
012366f
7802a01
3c74bde
58b7fce
d1bf8b5
76ab1bd
ef89710
db8a583
038c46d
5f0bee5
06e0bff
c6c6231
47b9a1b
b81ef32
8e910c0
4a41b47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| columns: | ||
| - [PRODUCT_ID, observation_id, text] | ||
| - [LINE_SAMPLES, samples, integer] | ||
| - [IMAGE_LINES, lines, integer] | ||
| - [CENTER_LATITUDE, center_latitude, real] | ||
| - [CENTER_LONGITUDE, center_longitude, real] | ||
| - [NORTH_AZIMUTH, north_azimuth, real] | ||
| - [SCALED_PIXEL_WIDTH, pixel_width, real] | ||
| - [VOLUME_ID, volume_id, text] | ||
| - [FILE_SPECIFICATION_NAME, file_specification_name, text] | ||
| - [PRODUCT_VERSION_ID, product_version_id, text] | ||
| - [TARGET_NAME, target_name, text] | ||
| - [ORBIT_NUMBER, orbit_number, integer] | ||
| - [MISSION_PHASE_NAME, mission_phase_name, text] | ||
| - [RATIONALE_DESC, description, text] | ||
| - [START_TIME, start_time, text] | ||
| - [STOP_TIME, stop_time, text] | ||
| - [SPACECRAFT_CLOCK_START_COUNT, sclk_start, real] | ||
| - [SPACECRAFT_CLOCK_STOP_COUNT, sclk_stop, real] | ||
| - [EMISSION_ANGLE, emission_angle, real] | ||
| - [INCIDENCE_ANGLE, incidence_angle, real] | ||
| - [PHASE_ANGLE, phase_angle, real] | ||
| - [SPACECRAFT_ALTITUDE, spacecraft_altitude, real] | ||
| - [TARGET_CENTER_DISTANCE, target_center_distance, real] | ||
| - [SUB_SOLAR_AZIMUTH, sub_solar_azimuth, real] | ||
| - [SUB_SOLAR_LATITUDE, sub_solar_latitude, real] | ||
| - [SUB_SOLAR_LONGITUDE, sub_solar_longitude, real] | ||
| - [SUB_SPACECRAFT_LATITUDE, sub_spacecraft_latitude, real] | ||
| - [SUB_SPACECRAFT_LONGITUDE, sub_spacecraft_longitude, real] | ||
| - [SOLAR_DISTANCE, solar_distance, real] | ||
| - [SOLAR_LONGITUDE, solar_longitude, real] | ||
| - [UPPER_RIGHT_LATITUDE, upper_right_latitude, real] | ||
| - [UPPER_RIGHT_LONGITUDE, upper_right_longitude, real] | ||
| - [LOWER_RIGHT_LATITUDE, lower_right_latitude, real] | ||
| - [LOWER_RIGHT_LONGITUDE, lower_right_longitude, real] | ||
| - [UPPER_LEFT_LATITUDE, upper_left_latitude, real] | ||
| - [UPPER_LEFT_LONGITUDE, upper_left_longitude, real] | ||
| - [LOWER_LEFT_LATITUDE, lower_left_latitude, real] | ||
| - [LOWER_LEFT_LONGITUDE, lower_left_longitude, real] | ||
|
|
||
| scale_factors: | ||
| SPACECRAFT_ALTITUDE: 1000 # km to m | ||
| SOLAR_DISTANCE: 1000 # km to m | ||
|
|
||
| index: | ||
| - observation_id | ||
|
|
||
| segmentation: | ||
| resolution: 50000 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,11 @@ | |
| TriSegmentedFootprint, SegmentTree) | ||
| from .util import standard_progress_bar | ||
|
|
||
| # https://tharsis.gsfc.nasa.gov/geodesy.html | ||
| MARS_RADIUS_M = 3396200. | ||
| #https://nssdc.gsfc.nasa.gov/planetary/factsheet/moonfact.html | ||
| MOON_RADIUS_M = 1736000 | ||
|
|
||
| DEFAULT_CONFIG_DIR = os.path.join( | ||
| os.path.dirname(os.path.realpath(__file__)), | ||
| 'config', | ||
|
|
@@ -134,7 +139,7 @@ def store_metadata(outputfile, instrument, table, config): | |
| for v in progress(cur.fetchall()) | ||
| ] | ||
|
|
||
| def store_segments(outputfile, metadata, config): | ||
| def store_segments(outputfile, metadata, config, body_radius=MARS_RADIUS_M): | ||
| """ | ||
| Segments observations corresponding to each entry in ``metadata``, and | ||
| stores these segments in a SQL database | ||
|
|
@@ -159,6 +164,8 @@ def store_segments(outputfile, metadata, config): | |
| - ``localizer_kwargs``: the ``kwargs`` that will be supplied to | ||
| the :py:meth:`~pdsc.localization.get_localizer` function for | ||
| determining observation footprints | ||
| :param body_radius: | ||
| radius of celestial body, default is mars | ||
|
|
||
| :return: a list of :py:class:`~pdsc.segment.TriSegment` objects for segments | ||
| across all observations | ||
|
|
@@ -172,11 +179,16 @@ def store_segments(outputfile, metadata, config): | |
| progress = standard_progress_bar('Segmenting footprints') | ||
| for m in progress(metadata): | ||
| try: | ||
| s = TriSegmentedFootprint(m, resolution, localizer_kwargs) | ||
| s = TriSegmentedFootprint(m, resolution, localizer_kwargs, body_radius) | ||
| for si in s.segments: | ||
| segments.append(si) | ||
| observation_ids.append(s.metadata.observation_id) | ||
|
|
||
| # erd: check if observation_id attribute exists | ||
| if hasattr(s.metadata, 'observation_id'): | ||
| observation_ids.append(s.metadata.observation_id) | ||
| else: | ||
| raise ValueError('Please rename your index col to observation_id in the config file') | ||
| # erd: lroc does not have observation_id | ||
| #observation_ids.append(s.metadata.file_specification_name) | ||
|
Comment on lines
+185
to
+191
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be preferable to check for this in the |
||
| except (TypeError, ValueError): | ||
| continue | ||
|
|
||
|
|
@@ -208,7 +220,7 @@ def store_segments(outputfile, metadata, config): | |
|
|
||
| return segments | ||
|
|
||
| def store_segment_tree(outputfile, segments): | ||
| def store_segment_tree(outputfile, segments, body_radius=MARS_RADIUS_M): | ||
| """ | ||
| Constructs a ball tree index for segmented observations and saves the | ||
| resulting data structure to the specified output file. | ||
|
|
@@ -218,8 +230,14 @@ def store_segment_tree(outputfile, segments): | |
|
|
||
| :param segments: | ||
| a collection of :py:class:`~pdsc.segment.TriSegment` objects | ||
|
|
||
| :body_radius: | ||
| celestial body radius, default is Mars | ||
| """ | ||
| tree = SegmentTree(segments) | ||
| if body_radius == MARS_RADIUS_M: | ||
| tree = SegmentTree(segments) | ||
| else: | ||
| tree = SegmentTree(segments, True, body_radius) | ||
|
Comment on lines
+237
to
+240
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can remove the |
||
| tree.save(outputfile) | ||
|
|
||
| def ingest_idx(label_file, table_file, configpath, outputdir): | ||
|
|
@@ -241,6 +259,14 @@ def ingest_idx(label_file, table_file, configpath, outputdir): | |
| will be stored | ||
| """ | ||
| instrument, table = parse_table(label_file, table_file) | ||
|
|
||
| if 'lroc' in instrument: | ||
| # use moon radius | ||
| body_radius = MOON_RADIUS_M | ||
| else: | ||
| # default radius is Mars | ||
| body_radius = MARS_RADIUS_M | ||
|
|
||
| if os.path.isdir(configpath): | ||
| configfile = os.path.join(configpath, '%s_metadata.yaml' % instrument) | ||
| else: | ||
|
|
@@ -266,10 +292,13 @@ def ingest_idx(label_file, table_file, configpath, outputdir): | |
| outputdir, | ||
| '%s%s' % (instrument, SEGMENT_DB_SUFFIX) | ||
| ) | ||
| segments = store_segments(outputfile, metadata, config) | ||
|
|
||
| segments = store_segments(outputfile, metadata, config, body_radius) | ||
|
|
||
| outputfile = os.path.join( | ||
| outputdir, | ||
| '%s%s' % (instrument, SEGMENT_TREE_SUFFIX) | ||
| ) | ||
| store_segment_tree(outputfile, segments) | ||
|
|
||
| store_segment_tree(outputfile, segments, body_radius) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,11 @@ | |
| MARS_RADIUS_M = 3396200. | ||
| MARS_FLATTENING = 1.0 / 169.8 | ||
|
|
||
| # erd: added moon info (before, assumed Mars only) | ||
| #https://nssdc.gsfc.nasa.gov/planetary/factsheet/moonfact.html | ||
| MOON_RADIUS_M = 1736000 | ||
| MOON_FLATTENING = 0.0012 | ||
|
|
||
| LOCALIZERS = {} | ||
|
|
||
| register_localizer = registerer(LOCALIZERS) | ||
|
|
@@ -63,6 +68,10 @@ def geodesic_distance(latlon1, latlon2, radius=MARS_RADIUS_M): | |
| >>> geodesic_distance((0, 0), (0, np.pi)) | ||
| 10669476.970121656 | ||
| """ | ||
| #print('The moons radius is: 1736000') | ||
| #print('Radius used is: ') | ||
| #print(radius) | ||
| #print('------') | ||
|
Comment on lines
+71
to
+74
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can remove comments |
||
| haversine = DistanceMetric.get_metric('haversine') | ||
| return float(radius*haversine.pairwise([latlon1], [latlon2])) | ||
|
|
||
|
|
@@ -198,6 +207,7 @@ def latlon_to_pixel(self, lat, lon, resolution_m=None, resolution_pix=0.1): | |
|
|
||
| loc = np.deg2rad([lat, lon]) | ||
|
|
||
| #print(self.BODY_RADIUS) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can remove comment |
||
| def f(u): | ||
| loc_u = np.deg2rad(self.pixel_to_latlon(*u)) | ||
| return geodesic_distance(loc, loc_u, self.BODY_RADIUS) | ||
|
|
@@ -217,6 +227,7 @@ class GeodesicLocalizer(Localizer): | |
| """ | ||
|
|
||
| BODY = Geodesic(MARS_RADIUS_M, MARS_FLATTENING) | ||
|
|
||
| """ | ||
| A :py:class:`~geographiclib.geodesic.Geodesic` object describing the target | ||
| body | ||
|
|
@@ -477,8 +488,9 @@ def __init__(self, proj_type, proj_latitude, proj_longitude, | |
| np.sqrt(a**2 + b**2) | ||
| ) | ||
| self.cos_proj_lat = np.cos(self.proj_latitude) | ||
|
|
||
| def _equirect_pixel_to_latlon(self, row, col): | ||
| # equations come from section 3.5.1 | ||
| # https://hirise.lpl.arizona.edu/pdf/HiRISE_RDR_v12_DTM_11_25_2009.pdf | ||
| x = (col - self.col_offset)*self.map_scale | ||
| y = -(row - self.row_offset)*self.map_scale | ||
| return ( | ||
|
|
@@ -513,6 +525,8 @@ def _polar_pixel_to_latlon(self, row, col): | |
| return lat, lon | ||
|
|
||
| def _polar_latlon_to_pixel(self, lat, lon): | ||
| # equations come from section 3.5.2 | ||
| # https://hirise.lpl.arizona.edu/pdf/HiRISE_RDR_v12_DTM_11_25_2009.pdf | ||
| lat_rad = np.deg2rad(lat) | ||
| lon_rad = np.deg2rad(lon % 360.) | ||
| T = np.tan((np.pi / 4.0) - np.abs(lat_rad / 2.0)) | ||
|
|
@@ -726,6 +740,64 @@ def __init__(self, metadata): | |
| corners, 1.0, 1.0, 1 | ||
| ) | ||
|
|
||
| class LrocCdrLocalizer(FourCornerLocalizer): | ||
| """ | ||
| A localizer for the LROC CDR observations (subclass of | ||
| :py:class:`FourCornerLocalizer`) | ||
| """ | ||
|
|
||
| DEFAULT_RESOLUTION_M = 1/3*(1e-6) | ||
| """ | ||
| Sets the default resolution for lroc CDR localization | ||
| 1/3 of that of HiRISE | ||
| """ | ||
|
|
||
| def __init__(self, metadata, downsamp): | ||
| """ | ||
| :param metadata: | ||
| "lroc_cdr" :py:class:`~pdsc.metadata.PdsMetadata` object | ||
| :param downsamp: | ||
| value of 1.0, no downsampling for LrocCdrLocalizer | ||
| """ | ||
| corners = np.array([ | ||
| [metadata.upper_left_latitude, metadata.upper_left_longitude], | ||
| [metadata.upper_right_latitude, metadata.upper_right_longitude], | ||
| [metadata.lower_right_latitude, metadata.lower_right_longitude], | ||
| [metadata.lower_left_latitude, metadata.lower_left_longitude], | ||
| ]) | ||
| super(LrocCdrLocalizer, self).__init__( | ||
| corners, metadata.lines/downsamp, metadata.samples/downsamp, 1 | ||
| ) | ||
|
|
||
| class LrocCdrBrowseLocalizer(LrocCdrLocalizer): | ||
| """ | ||
| A localizer for the LROC CDR observations (subclass of | ||
| :py:class:`FourCornerLocalizer`) | ||
| """ | ||
|
|
||
| DEFAULT_RESOLUTION_M = 1/3*(1e-6)*2 | ||
| """ | ||
| Sets the default resolution for lroc CDR localization | ||
| 1/3 of that of HiRISE, plus factor of 2 for browse | ||
| """ | ||
|
|
||
| LROC_DOWNSAMP = 2.0 | ||
| """ | ||
| The default downsample amount for browse imagery | ||
| """ | ||
|
|
||
| def __init__(self, metadata, downsamp): | ||
| """ | ||
| :param metadata: | ||
| "lroc_cdr" :py:class:`~pdsc.metadata.PdsMetadata` object | ||
| :param downsamp: | ||
| the downsample amount of lroc browse image (if it varies from the default | ||
| value) | ||
| """ | ||
| if downsamp < 1: | ||
| raise ValueError('Invalid downsample: %f' % downsamp) | ||
| super(LrocCdrBrowseLocalizer, self).__init__(metadata, downsamp) | ||
|
|
||
| class HiRiseRdrLocalizer(MapLocalizer): | ||
| """ | ||
| A localizer for the HiRISE RDR (map-projected) observations (subclass of | ||
|
|
@@ -817,6 +889,25 @@ def hirise_rdr_localizer(metadata, nomap=False, browse=False, | |
| else: | ||
| return HiRiseRdrLocalizer(metadata) | ||
|
|
||
| @register_localizer('lroc_cdr') | ||
| def lroc_cdr_localizer(metadata, browse=False, downsamp=LrocCdrBrowseLocalizer.LROC_DOWNSAMP): | ||
| """ | ||
| Constructs the LROC CDR localizer (data is not map projected) | ||
|
|
||
| :param metadata: | ||
| "lroc_cdr" :py:class:`~pdsc.metadata.PdsMetadata` object | ||
| :param browse: | ||
| construct localizer for the BROWSE data product | ||
| :param downsamp: | ||
| if ``browse=True``, use this value for the downsample amount | ||
|
|
||
| :return: a :py:class:`Localizer` for the appropriate data product | ||
| """ | ||
| if browse: | ||
| return LrocCdrBrowseLocalizer(metadata, downsamp) | ||
| else: | ||
| return LrocCdrLocalizer(metadata, 1.0) | ||
|
|
||
| @register_localizer('moc') | ||
| class MocLocalizer(GeodesicLocalizer): | ||
| """ | ||
|
|
@@ -855,9 +946,9 @@ def get_localizer(metadata, *args, **kwargs): | |
|
|
||
| :param metadata: | ||
| a :py:class:`~pdsc.metadata.PdsMetadata` object for an observation | ||
| :param \*args: | ||
| :param *args: | ||
| additional args provided to the localizer constructor | ||
| :param \**kwargs: | ||
| :param **kwargs: | ||
| additional kwargs provided to the localizer constructor | ||
|
|
||
| :return: a :py:class:`Localizer` for the observation | ||
|
|
@@ -871,5 +962,4 @@ def get_localizer(metadata, *args, **kwargs): | |
| if metadata.instrument not in LOCALIZERS: | ||
| raise IndexError( | ||
| 'No localizer implemented for %s' % metadata.instrument) | ||
|
|
||
| return LOCALIZERS[metadata.instrument](metadata, *args, **kwargs) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be preferable to import from
localization.pyrather than duplicate