Removed the subdir.
This commit is contained in:
0
pyrate/tests/common/__init__.py
Normal file
0
pyrate/tests/common/__init__.py
Normal file
0
pyrate/tests/common/charts/__init__.py
Normal file
0
pyrate/tests/common/charts/__init__.py
Normal file
1
pyrate/tests/common/charts/example_charts/README.txt
Normal file
1
pyrate/tests/common/charts/example_charts/README.txt
Normal file
@ -0,0 +1 @@
|
||||
See https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/data/-/tree/master/charts/noaa_vector for the license and more information.
|
@ -0,0 +1,71 @@
|
||||
NOAA ENC<4E>
|
||||
|
||||
NATIONAL OCEANIC AND ATMOSPHERIC ADMINISTRATION
|
||||
|
||||
US1BS04M - BERING SEA NORTHERN PART (EAST)
|
||||
|
||||
|
||||
INDEX:
|
||||
NOTE A
|
||||
AIDS TO NAVIGATION
|
||||
CAUTION - TEMPORARY CHANGES
|
||||
CAUTION - LIMITATIONS
|
||||
NOTE B
|
||||
WARNING - PRUDENT MARINER
|
||||
AUTHORITIES
|
||||
INTERNATIONAL BOUNDARIES
|
||||
POLLUTION REPORTS
|
||||
CAUTION - DANGER
|
||||
ADDITIONAL INFORMATION
|
||||
|
||||
|
||||
NOTES:
|
||||
NOTE A
|
||||
Navigation regulations are published in Chapter 2, U.S. Coast Pilot 9. Additions or revisions to Chapter 2 are published in the Notice to Mariners. Information concerning the regulations may be obtained at the Office of the Commander, 17th Coast Guard District in Juneau, Alaska or at the Office of the District Engineer, Corps of Engineers in Anchorage, Alaska.
|
||||
Refer to charted regulation section numbers.
|
||||
|
||||
|
||||
AIDS TO NAVIGATION
|
||||
Consult U.S. Coast Guard Light List for supplemental information concerning aids to navigation.
|
||||
|
||||
See National Geospatial-Intelligence Agency List of Lights and Fog Signals for information not included in the United States Coast Guard Light List.
|
||||
|
||||
|
||||
CAUTION - TEMPORARY CHANGES
|
||||
Temporary changes or defects in aids to navigation are not indicated. See Local Notice to Mariners.
|
||||
|
||||
|
||||
CAUTION - LIMITATIONS
|
||||
Limitations on the use of radio signals as aids to marine navigation can be found in the U.S. Coast Guard Light Lists and National Geospatial-Intelligence Agency Publication 117.
|
||||
Radio direction-finder bearings to commercial broadcasting stations are subject to error and should be used with caution.
|
||||
|
||||
|
||||
NOTE B
|
||||
Radio navigational aids on the Russian Arctic coast and adjacent islands north of the Arctic Circle have been omitted due to the lack of reliable information.
|
||||
|
||||
|
||||
WARNING - PRUDENT MARINER
|
||||
The prudent mariner will not rely solely on any single aid to navigation, particularly on floating aids. See U.S. Coast Guard Light List and U.S. Coast Pilot for details.
|
||||
|
||||
|
||||
AUTHORITIES
|
||||
Hydrography and topography by the National Ocean Service, Coast Survey, with additional data from the U.S. Coast Guard, National Geospatial Intelligence Agency, and the Japanese Hydrographic Department.
|
||||
|
||||
|
||||
INTERNATIONAL BOUNDARIES
|
||||
International boundaries as shown are approximate.
|
||||
|
||||
|
||||
POLLUTION REPORTS
|
||||
Report all spills of oil and hazardous substances to the National Response Center via 1-800-424-8802 (toll free), or to the nearest U.S. Coast Guard facility if telephone communication is impossible (33 CFR 153).
|
||||
|
||||
|
||||
CAUTION - DANGER
|
||||
Danger, Prohibited, and Restricted Area falling within the limits of the larger scale charts are shown thereon and not repeated.
|
||||
|
||||
|
||||
ADDITIONAL INFORMATION
|
||||
Additional information can be obtained at www.nauticalcharts.noaa.gov
|
||||
|
||||
|
||||
END OF FILE
|
@ -0,0 +1,6 @@
|
||||
Maritime boundary provisionally applied pending formal exchange of instruments of ratification.
|
||||
|
||||
According to Article 3 of the Agreement Between the United States of America and Russia on the Maritime Boundary, signed June 1, 1990:
|
||||
|
||||
"1. In any area east of the maritime boundary that lies within 200 nautical miles of the baseline from which the breadth of the territorial sea of Russia is measured but beyond 200 nautical miles of the baselines from which the breadth of the territorial sea of the United States is measured ("eastern special area"), Russia agrees that henceforth the United States may exercise the sovereign rights and jurisdiction derived from exclusive economic zone jurisdiction that Russia would otherwise be entitled to exercise under international law in the absence of the agreement of the Parties on the maritime boundary...
|
||||
3. to the extent that either Party exercises the sovereign rights or jurisdiction in the special area or areas on its side of the maritime boundary as provided for in this Article, such exercise of sovereign rights or jurisdiction derives from the agreement of the Parties and does not constitute an extension of its exclusive economic zone. To this end, each Party shall take the necessary steps to ensure that any exercise on its part of such rights or jurisdiction in the special area or areas on its side of the maritime boundary shall be so characterized in its relevant laws, regulations, and charts."
|
@ -0,0 +1,2 @@
|
||||
CAUTION - QUALITY OF BATHYMETRIC DATA
|
||||
The areas represented by the object M_QUAL (Quality of data) are approximate due to generalizing for clarity. Caution is advised, particularly for nearshore navigation or voyage planning. M_QUAL represents areas of uniform quality of bathymetric data. The CATZOC (Category of zone of confidence in data) attribute of M_QUAL provides an assessment of the overall zone of confidence.
|
BIN
pyrate/tests/common/charts/example_charts/US1BS04M/US1BS04M.000
Normal file
BIN
pyrate/tests/common/charts/example_charts/US1BS04M/US1BS04M.000
Normal file
Binary file not shown.
@ -0,0 +1,97 @@
|
||||
NOAA ENC<4E>
|
||||
|
||||
NATIONAL OCEANIC AND ATMOSPHERIC ADMINISTRATION
|
||||
|
||||
US4AK5GM - PORT MOLLER AND HERENDEEN BAY
|
||||
|
||||
INDEX:
|
||||
|
||||
AIDS TO NAVIGATION
|
||||
POLLUTION REPORTS
|
||||
CAUTION USE OF RADIO SIGNALS (LIMITATIONS)
|
||||
SUPPLEMENTAL INFORMATION
|
||||
CAUTION - TEMPORARY CHANGES
|
||||
WARNING - PRUDENT MARINER
|
||||
ADDITIONAL INFORMATION
|
||||
NOTE A
|
||||
AUTHORITIES
|
||||
CAUTION - LIMITATIONS
|
||||
CAUTION - CHANNELS
|
||||
RADAR REFLECTORS
|
||||
NOAA WEATHER RADIO BROADCASTS
|
||||
TIDAL INFORMATION
|
||||
ADMINISTRATION AREA
|
||||
COLREGS, 82.1705 (see note A)
|
||||
|
||||
|
||||
|
||||
NOTES:
|
||||
|
||||
AIDS TO NAVIGATION
|
||||
Consult U.S. Coast Guard Light List for supplemental information concerning aids to navigation.
|
||||
|
||||
|
||||
POLLUTION REPORTS
|
||||
Report all spills of oil and hazardous substances to the National Response Center via 1-800-424-8802 (toll free), or to the nearest U.S. Coast Guard facility if telephone communication is impossible (33 CFR 153).
|
||||
|
||||
|
||||
CAUTION USE OF RADIO SIGNALS (LIMITATIONS)
|
||||
Limitations on the use of radio signals as aids to marine navigation can be found in the U.S. Coast Guard Light Lists and National Geospatial-Intelligence Agency Publication 117. Radio direction-finder bearings to commercial broadcasting stations are subject to error and should be used with caution.
|
||||
|
||||
|
||||
SUPPLEMENTAL INFORMATION
|
||||
Consult U.S. Coast Pilot 9 for important supplemental information.
|
||||
|
||||
|
||||
CAUTION - TEMPORARY CHANGES
|
||||
Temporary changes or defects in aids to navigation are not indicated. See Local Notice to Mariners
|
||||
|
||||
|
||||
WARNING - PRUDENT MARINER
|
||||
The prudent mariner will not rely solely on any single aid to navigation, particularly on floating aids. See U.S. Coast Guard Light List and U.S. Coast Pilot for details.
|
||||
|
||||
|
||||
ADDITIONAL INFORMATION
|
||||
Additional information can be obtained at www.nauticalcharts.noaa.gov
|
||||
|
||||
|
||||
NOTE A
|
||||
Navigation regulations are published in Chapter 2, U.S. Coast Pilot 9. Additions or revisions to Chapter 2 are published in the Notice to Mariners. Information concerning
|
||||
the regulations may be obtained at the Office of the Commander, 17th Coast Guard District in Juneau, Alaska, or at the Office of the District Engineer, Corps of Engineers in Anchorage, Alaska. Refer to charted regulation section numbers
|
||||
|
||||
|
||||
AUTHORITIES
|
||||
Hydrography and Topography by the National Ocean Service, Coast Survey, with additional data from the U.S. Coast Guard.
|
||||
|
||||
|
||||
CAUTION - LIMITATIONS
|
||||
Limitations on the use of radio signals as aids to marine navigation can be found in the U.S. Coast Guard Light Lists and National Geospatial-Intelligence Agency Publication 117. Radio direction-finder bearings to commercial broadcasting stations are subject to error and should be used with caution.CAUTION - CHANNELS Channels are subject to frequent changes due to very strong tidal currents.
|
||||
|
||||
|
||||
CAUTION - CHANNELS
|
||||
Channels are subject to frequent changes due to very strong tidal currents.
|
||||
|
||||
RADAR REFLECTORS
|
||||
Radar reflectors have been placed on many floating aids to navigation. Individual radar
|
||||
reflector identification on these aids has been omitted from this chart.
|
||||
|
||||
|
||||
NOAA WEATHER RADIO BROADCASTS
|
||||
The NOAA Weather Radio station listed below provides continuous weather broadcasts. The reception range is typically 20 to 40 nautical miles from the antenna site, but can be as much as 100 nautical miles for stations at high elevations.
|
||||
|
||||
Sand Point, AK KSDP 840 AM
|
||||
|
||||
|
||||
TIDAL INFORMATION
|
||||
For tidal information see the NOS Tide Table publication or go to http://co-ops.nos.noaa.gov
|
||||
|
||||
|
||||
ADMINISTRATION AREA
|
||||
The entire extent of this ENC cell falls within the limits of an Administration Area. This area covers land, internal waters, and territorial sea. The territorial sea is a maritime zone which the United States exercises sovereignty extending to the airspace as well as to its bed and subsoil. For more information, please refer to the Coast Pilot.
|
||||
|
||||
|
||||
COLREGS, 82.1705 (see note A)
|
||||
International Regulations for Preventing Collisions at Sea, 1972. The entire area of this chart falls seaward of the COLREGS Demarcation Line.
|
||||
|
||||
|
||||
END OF FILE
|
@ -0,0 +1,2 @@
|
||||
CAUTION - QUALITY OF BATHYMETRIC DATA
|
||||
The areas represented by the object M_QUAL (Quality of data) are approximate due to generalizing for clarity. Caution is advised, particularly for nearshore navigation or voyage planning. M_QUAL represents areas of uniform quality of bathymetric data. The CATZOC (Category of zone of confidence in data) attribute of M_QUAL provides an assessment of the overall zone of confidence.
|
BIN
pyrate/tests/common/charts/example_charts/US4AK5GM/US4AK5GM.000
Normal file
BIN
pyrate/tests/common/charts/example_charts/US4AK5GM/US4AK5GM.000
Normal file
Binary file not shown.
BIN
pyrate/tests/common/charts/example_charts/US4AK5GM/US4AK5GM.001
Normal file
BIN
pyrate/tests/common/charts/example_charts/US4AK5GM/US4AK5GM.001
Normal file
Binary file not shown.
144
pyrate/tests/common/charts/example_charts/US4FL87M/US4FL87A.TXT
Normal file
144
pyrate/tests/common/charts/example_charts/US4FL87M/US4FL87A.TXT
Normal file
@ -0,0 +1,144 @@
|
||||
NOAA ENC<4E>
|
||||
|
||||
NATIONAL OCEANIC AND ATMOSPHERIC ADMINISTRATION
|
||||
|
||||
US4FL87M - CAPE CANAVERAL TO BETHEL SHOAL
|
||||
|
||||
INDEX:
|
||||
NOTE A
|
||||
AIDS TO NAVIGATION
|
||||
NOAA WEATHER BROADCASTS
|
||||
CAUTION - TEMPORARY CHANGES
|
||||
CAUTION - DREDGED AREAS
|
||||
SUPPLEMENTAL INFORMATION
|
||||
AUTHORITIES
|
||||
POLLUTION REPORTS
|
||||
RADAR REFLECTORS
|
||||
WARNING - PRUDENT MARINER
|
||||
CAUTION - SUBMARINE PIPELINES AND CABLES
|
||||
HURRICANES AND TROPICAL STORMS
|
||||
CAUTION - LIMITATIONS
|
||||
ADDITIONAL INFORMATION
|
||||
TIDAL INFORMATION
|
||||
CAUTION - USACE HYDROGRAPHIC SURVEYS
|
||||
|
||||
|
||||
NOTES:
|
||||
NOTE A
|
||||
Navigation regulations are published in Chapter 2, U.S.
|
||||
Coast Pilot 4. Additions or revisions to Chapter 2 are pub-
|
||||
lished in the Notice to Mariners. Information concerning the
|
||||
regulations may be obtained at the Office of the Commander,
|
||||
7th Coast Guard District in Miami, Florida, or at the Office
|
||||
of the District Engineer, Corps of Engineers in Jacksonville,
|
||||
Florida.
|
||||
Refer to charted regulation section numbers.
|
||||
|
||||
AIDS TO NAVIGATION
|
||||
Consult U.S. Coast Guard Light List for
|
||||
supplemental information concerning aids to
|
||||
navigation.
|
||||
|
||||
NOAA WEATHER BROADCASTS
|
||||
The NOAA Weather Radio stations listed
|
||||
below provide continuous weather broadcasts.
|
||||
The reception range is typically 20 to 40
|
||||
nautical miles from the antenna site, but can be
|
||||
as much as 100 nautical miles for stations at
|
||||
high elevations.
|
||||
|
||||
Melbourne, FL WXJ-70 162.550 MHz
|
||||
Fort Pierce, FL WWF-69 162.425 MHz
|
||||
|
||||
CAUTION - TEMPORARY CHANGES
|
||||
Temporary changes or defects in aids to
|
||||
navigation are not indicated.
|
||||
See Local Notice to Mariners.
|
||||
|
||||
CAUTION - DREDGED AREAS
|
||||
Improved channels are
|
||||
subject to shoaling, particularly at the edges.
|
||||
|
||||
SUPPLEMENTAL INFORMATION
|
||||
Consult U.S. Coast Pilot 4 for important
|
||||
supplemental information.
|
||||
|
||||
AUTHORITIES
|
||||
Hydrography and topography by the National Ocean Service, Coast
|
||||
Survey, with additional data from the Corps of Engineers, and U.S.
|
||||
Coast Guard.
|
||||
|
||||
POLLUTION REPORTS
|
||||
Report all spills of oil and hazardous sub-
|
||||
stances to the National Response Center via
|
||||
1-800-424-8802 (toll free), or to the nearest U.S.
|
||||
Coast Guard facility if telephone communication
|
||||
is impossible (33 CFR 153).
|
||||
|
||||
RADAR REFLECTORS
|
||||
Radar reflectors have been placed on many
|
||||
floating aids to navigation. Individual radar
|
||||
reflector identification on these aids has been
|
||||
omitted from this chart.
|
||||
|
||||
WARNING - PRUDENT MARINER
|
||||
The prudent mariner will not rely solely on
|
||||
any single aid to navigation, particularly on
|
||||
floating aids. See U.S. Coast Guard Light List
|
||||
and U.S. Coast Pilot for details.
|
||||
|
||||
CAUTION - SUBMARINE PIPELINES AND CABLES
|
||||
Additional uncharted submarine pipelines and
|
||||
submarine cables may exist within the area of
|
||||
this chart. Not all submarine pipelines and sub-
|
||||
marine cables are required to be buried, and
|
||||
those that were originally buried may have
|
||||
become exposed. Mariners should use extreme
|
||||
caution when operating vessels in depths of
|
||||
water comparable to their draft in areas where
|
||||
pipelines and cables may exist, and when
|
||||
anchoring, dragging, or trawling.
|
||||
Covered wells may be marked by lighted or
|
||||
unlighted buoys.
|
||||
|
||||
HURRICANES AND TROPICAL STORMS
|
||||
Hurricanes, tropical storms and other major storms may
|
||||
cause considerable damage to marine structures, aids to
|
||||
navigation and moored vessels, resulting in submerged debris
|
||||
in unknown locations.
|
||||
Charted soundings, channel depths and shoreline may not
|
||||
reflect actual conditions following these storms. Fixed aids to
|
||||
navigation may have been damaged or destroyed. Buoys may
|
||||
have been moved from their charted positions, damaged, sunk,
|
||||
extinguished or otherwise made inoperative. Mariners should
|
||||
not rely upon the position or operation of an aid to navigation.
|
||||
Wrecks and submerged obstructions may have been displaced
|
||||
from charted locations. Pipelines may have become uncovered
|
||||
or moved.
|
||||
Mariners are urged to exercise extreme caution and are
|
||||
requested to report aids to navigation discrepancies and
|
||||
hazards to navigation to the nearest United States Coast Guard
|
||||
unit.
|
||||
|
||||
CAUTION - LIMITATIONS
|
||||
Limitations on the use of radio signals as
|
||||
aids to marine navigation can be found in the
|
||||
U.S. Coast Guard Light Lists and National
|
||||
Geospatial-Intelligence Agency Publication 117.
|
||||
Radio direction-finder bearings to commercial
|
||||
broadcasting stations are subject to error and
|
||||
should be used with caution.
|
||||
|
||||
ADDITIONAL INFORMATION
|
||||
Additional information can be obtained at www.nauticalcharts.noaa.gov
|
||||
|
||||
TIDAL INFORMATION
|
||||
For tidal information see the NOS Tide Table publication or go to http://co-ops.nos.noaa.gov.
|
||||
|
||||
CAUTION - USACE HYDROGRAPHIC SURVEYS
|
||||
USACE conducts hydrographic surveys to monitor navigation conditions.
|
||||
These surveys are not intended to detect underwater features. Uncharted features hazardous to surface navigation are not expected but may exist in federal channels.
|
||||
|
||||
|
||||
|
||||
END OF FILE
|
@ -0,0 +1,16 @@
|
||||
Exclusive Economic Zone (EEZ)
|
||||
The EEZ is a zone beyond and adjacent to the territorial sea within which the U.S. has certain
|
||||
sovereign rights and jurisdiction. Under some U.S. laws, the inner limit of the EEZ extends landward
|
||||
to the seaward limit of the states submerged lands. For more information, please refer to the Coast
|
||||
Pilot.
|
||||
|
||||
Contiguous Zone
|
||||
The Contiguous Zone is a zone contiguous to the territorial sea, in which the United States may
|
||||
exercise the control necessary to prevent and punish infringement within its territory or territorial sea
|
||||
of its customs, fiscal, immigration, cultural heritage or sanitary laws and regulations. For more
|
||||
information, please refer to the Coast Pilot.
|
||||
|
||||
Administration Area
|
||||
This area covers land, internal waters, and territorial sea. The territorial sea is a maritime zone over
|
||||
which the United States exercises sovereignty extending to the airspace as well as to its bed and
|
||||
subsoil. For more information, please refer to the Coast Pilot.
|
@ -0,0 +1,14 @@
|
||||
The Inland Navigational Rules Act of 1980 is in effect for vessels transiting this
|
||||
area. The seaward boundaries of this area are the COLREGS demarcation lines.
|
||||
In the area seaward of the COLREGS demarcation lines, vessels are governed by
|
||||
COLREGS: International Regulations for Preventing Collisions at Sea, 1972.
|
||||
The COLREGS demarcation lines are defined in 33 CFR 80.727b.
|
||||
|
||||
Navigation regulations are published in Chapter 2, U.S.
|
||||
Coast Pilot 4. Additions or revisions to Chapter 2 are pub-
|
||||
lished in the Notice to Mariners. Information concerning the
|
||||
regulations may be obtained at the Office of the Commander,
|
||||
7th Coast Guard District in Miami, Florida, or at the Office
|
||||
of the District Engineer, Corps of Engineers in Jacksonville,
|
||||
Florida.
|
||||
Refer to charted regulation section numbers.
|
@ -0,0 +1 @@
|
||||
Depths from surveys of 2000-2007 - Regulations for Ocean Dumping Sites are contained in 40 CFR, Parts 220-229. Additional information concerning the regulations and requirements for use of the sites may be obtained from the Environmental Protection Agency (EPA). See U.S. Coast Pilots appendix for addresses of EPA offices. Dumping subsequent to the survey dates may have reduced the depths shown.
|
@ -0,0 +1,2 @@
|
||||
This area represents the limits of the Low-Mid Inclination launch hazard areas associated with the majority of launches from Cape Canaveral. Launch debris may fall within these areas. See Notice to Mariners or contact the Coast Guard for launch hazard areas specific to each launch and the times they will be in effect.
|
||||
|
@ -0,0 +1 @@
|
||||
This area represents the limits of the High Inclination launch hazard areas associated with the majority of launches from Cape Canaveral. Launch debris may fall within these areas. See Notice to Mariners or contact the Coast Guard for launch hazard areas specific to each launch and the times they will be in effect.
|
@ -0,0 +1,6 @@
|
||||
CAUTION <20> QUALITY OF BATHYMETRIC DATA
|
||||
The areas represented by the object M_QUAL (Quality of data) are approximate due
|
||||
to generalizing for clarity. Caution is advised, particularly for nearshore navigation
|
||||
or voyage planning. M_QUAL represents areas of uniform quality of bathymetric data.
|
||||
The CATZOC (Category of zone of confidence in data) attribute of M_QUAL provides
|
||||
an assessment of the overall zone of confidence.
|
BIN
pyrate/tests/common/charts/example_charts/US4FL87M/US4FL87M.000
Normal file
BIN
pyrate/tests/common/charts/example_charts/US4FL87M/US4FL87M.000
Normal file
Binary file not shown.
BIN
pyrate/tests/common/charts/example_charts/US4FL87M/US4FL87M.001
Normal file
BIN
pyrate/tests/common/charts/example_charts/US4FL87M/US4FL87M.001
Normal file
Binary file not shown.
@ -0,0 +1,132 @@
|
||||
NOAA ENC<4E>
|
||||
|
||||
NATIONAL OCEANIC AND ATMOSPHERIC ADMINISTRATION
|
||||
|
||||
US4VA70M - CHINCOTEAGUE INLET TO GREAT MACHIPONGO INLET
|
||||
|
||||
INDEX
|
||||
AUTHORITIES
|
||||
AIDS TO NAVIGATION
|
||||
NOTE A
|
||||
WARNING - PRUDENT MARINER
|
||||
POLLUTION REPORTS
|
||||
SUPPLEMENTAL INFORMATION
|
||||
CAUTION - TEMPORARY CHANGES
|
||||
CAUTION - LIMITATIONS
|
||||
CAUTION - SUBMARINE PIPELINES AND CABLES
|
||||
RADAR REFLECTORS
|
||||
NOAA WEATHER BROADCASTS
|
||||
CAUTION - DREDGED AREAS
|
||||
TIDAL INFORMATION
|
||||
ADDITIONAL INFORMATION
|
||||
|
||||
|
||||
NOTES:
|
||||
AUTHORITIES
|
||||
Hydrography and Topography by the National Ocean Service, Coast
|
||||
Survey, with additional data from the Corps of Engineers, Geological
|
||||
Survey, and U.S. Coast Guard.
|
||||
|
||||
|
||||
AIDS TO NAVIGATION
|
||||
Consult U.S. Coast Guard Light List for
|
||||
supplemental information concerning aids to
|
||||
navigation.
|
||||
|
||||
|
||||
NOTE A
|
||||
Navigation regulations are published in Chapter 2, U.S.
|
||||
Coast Pilot 3. Additions or revisions to Chapter 2 are pub-
|
||||
lished in the Notice to Mariners. Information concerning the
|
||||
regulations may be obtained at the Office of the Commander,
|
||||
5th Coast Guard District in Portsmouth, Virginia or at the
|
||||
Office of the District Engineer, Corps of Engineers in
|
||||
Norfolk, Virginia.
|
||||
Refer to charted regulation section numbers.
|
||||
|
||||
|
||||
WARNING - PRUDENT MARINER
|
||||
The prudent mariner will not rely solely on
|
||||
any single aid to navigation, particularly on
|
||||
floating aids. See U.S. Coast Guard Light List
|
||||
and U.S. Coast Pilot for details.
|
||||
|
||||
|
||||
POLLUTION REPORTS
|
||||
Report all spills of oil and hazardous substances to the
|
||||
National Response Center via 1-800-424-8802 (toll free), or
|
||||
to the nearest U.S. Coast Guard facility if telephone com-
|
||||
munication is impossible (33 CFR 153).
|
||||
|
||||
|
||||
SUPPLEMENTAL INFORMATION
|
||||
Consult U.S. Coast Pilot 3 for important
|
||||
supplemental information.
|
||||
|
||||
|
||||
CAUTION - TEMPORARY CHANGES
|
||||
Temporary changes or defects in aids to
|
||||
navigation are not indicated. See
|
||||
Local Notice to Mariners.
|
||||
|
||||
|
||||
CAUTION - LIMITATIONS
|
||||
Limitations on the use of radio signals as
|
||||
aids to marine navigation can be found in the
|
||||
U.S. Coast Guard Light Lists and National
|
||||
Geospatial-Intelligence Agency Publication 117.
|
||||
Radio direction-finder bearings to commercial
|
||||
broadcasting stations are subject to error and
|
||||
should be used with caution.
|
||||
|
||||
|
||||
CAUTION - SUBMARINE PIPELINES AND CABLES
|
||||
Additional uncharted submarine pipelines and
|
||||
submarine cables may exist within the area of
|
||||
this chart. Not all submarine pipelines and sub-
|
||||
marine cables are required to be buried, and
|
||||
those that were originally buried may have
|
||||
become exposed. Mariners should use extreme
|
||||
caution when operating vessels in depths of
|
||||
water comparable to their draft in areas where
|
||||
pipelines and cables may exist, and when
|
||||
anchoring, dragging, or trawling.
|
||||
Covered wells may be marked by lighted or
|
||||
unlighted buoys.
|
||||
|
||||
|
||||
RADAR REFLECTORS
|
||||
Radar reflectors have been placed on many
|
||||
floating aids to navigation. Individual radar
|
||||
reflector identification on these aids has been
|
||||
omitted from this chart.
|
||||
|
||||
|
||||
NOAA WEATHER RADIO BROADCASTS
|
||||
The NOAA Weather Radio stations listed
|
||||
below provide continuous weather broadcasts.
|
||||
The reception range is typically 37 to 74 kilometers / 20
|
||||
to 40 nautical miles from the antenna site, but can be
|
||||
as much as 100 nautical miles / 185 kilometers for stations at
|
||||
high elevations.
|
||||
|
||||
Norfolk, VA KHB-37 162.550 MHz
|
||||
Salisbury, MD KEC-92 162.475 MHz
|
||||
Heathsville, VA WXM-57 162.400 MHz
|
||||
|
||||
|
||||
CAUTION - DREDGED AREAS
|
||||
Improved channels are
|
||||
subject to shoaling, particularly at the edges.
|
||||
|
||||
|
||||
TIDAL INFORMATION
|
||||
For tidal information see the NOS tide table publication or go to http://co-ops.nos.noaa.gov.
|
||||
|
||||
|
||||
ADDITIONAL INFORMATION
|
||||
Additional information can be obtained at www.nauticalcharts.noaa.gov
|
||||
|
||||
|
||||
END OF FILE
|
||||
|
@ -0,0 +1,8 @@
|
||||
Exclusive Economic Zone (EEZ)
|
||||
The EEZ is a zone beyond and adjacent to the territorial sea within which the U.S. has certain sovereign rights and jurisdiction. Under some U.S. laws, the inner limit of the EEZ extends landward to the seaward limit of the states submerged lands. For more information, please refer to the Coast Pilot.
|
||||
|
||||
Contiguous Zone
|
||||
The Contiguous Zone is a zone contiguous to the territorial sea, in which the United States may exercise the control necessary to prevent and punish infringement within its territory or territorial sea of its customs, fiscal, immigration, cultural heritage or sanitary laws and regulations. For more information, please refer to the Coast Pilot.
|
||||
|
||||
Administration Area
|
||||
This area covers land, internal waters, and territorial sea. The territorial sea is a maritime zone over which the United States exercises sovereignty extending to the airspace as well as to its bed and subsoil. For more information, please refer to the Coast Pilot.
|
@ -0,0 +1 @@
|
||||
Mariners are warned that numerous uncharted duck blinds, stakes, and fishing structures, some submerged, may exist in the fish trap areas. Such structures are not charted unless known to be permanent.
|
@ -0,0 +1,17 @@
|
||||
The Inland Navigational Rules Act of 1980 is in effect for vessels
|
||||
transiting this area. The seaward boundaries of this area are the COLREGS
|
||||
demarcation lines. In the area seaward of the COLREGS demarcation lines, vessels
|
||||
are governed by COLREGS: International Regulations for Prevention of Collisions
|
||||
at Sea, 1972. The COLREGS demarcation lines are defined in 33 CFR 80.505c,
|
||||
33 CFR 80.505d, 33 CFR 80.505e and 33 CFR 505h.
|
||||
|
||||
|
||||
NOTE A
|
||||
Navigation regulations are published in Chapter 2, U.S.
|
||||
Coast Pilot 3. Additions or revisions to Chapter 2 are pub-
|
||||
lished in the Notice to Mariners. Information concerning the
|
||||
regulations may be obtained at the Office of the Commander,
|
||||
5th Coast Guard District in Portsmouth, Virginia or at the
|
||||
Office of the District Engineer, Corps of Engineers in
|
||||
Norfolk, Virginia.
|
||||
Refer to charted regulation section numbers.
|
@ -0,0 +1,6 @@
|
||||
CAUTION - QUALITY OF BATHYMETRIC DATA
|
||||
The areas represented by the object M_QUAL (Quality of data) are approximate
|
||||
due to generalizing for clarity. Caution is advised, particularly for nearshore
|
||||
navigation or voyage planning. M_QUAL represents areas of uniform quality of
|
||||
bathymetric data. The CATZOC (Category of zone of confidence in data) attribute
|
||||
of M_QUAL provides an assessment of the overall zone of confidence.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
||||
This should not be found by the discovery chart tests.
|
469
pyrate/tests/common/charts/test_db.py
Normal file
469
pyrate/tests/common/charts/test_db.py
Normal file
@ -0,0 +1,469 @@
|
||||
"""This module tests if the database abstraction is working correctly."""
|
||||
|
||||
# Standard library
|
||||
from io import StringIO
|
||||
from os.path import join
|
||||
import sqlite3
|
||||
from tempfile import TemporaryDirectory
|
||||
import warnings
|
||||
|
||||
# Typing
|
||||
from typing import cast
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
# Unit testing
|
||||
from unittest.mock import patch
|
||||
from unittest import skip
|
||||
from unittest import skipIf
|
||||
from unittest import TestCase
|
||||
|
||||
# Verification
|
||||
from hypothesis import given
|
||||
from hypothesis import HealthCheck
|
||||
from hypothesis import settings
|
||||
import hypothesis.strategies as st
|
||||
import numpy
|
||||
|
||||
# Geometry
|
||||
from shapely.geometry import Point
|
||||
|
||||
# Package under test
|
||||
from pyrate.common.charts.db import to_wkb
|
||||
from pyrate.common.charts import SpatialiteDatabase
|
||||
from pyrate.plan.geometry import CartesianLocation
|
||||
from pyrate.plan.geometry import CartesianPolygon
|
||||
from pyrate.plan.geometry import Geospatial
|
||||
from pyrate.plan.geometry import LocationType
|
||||
from pyrate.plan.geometry import PolarGeometry
|
||||
from pyrate.plan.geometry import PolarLocation
|
||||
from pyrate.plan.geometry import PolarPolygon
|
||||
from pyrate.plan.geometry import PolarRoute
|
||||
|
||||
# Flags and helpers
|
||||
from pyrate.common.testing import IS_CI
|
||||
from pyrate.common.testing import IS_EXTENDED_TESTING
|
||||
from pyrate.common.testing import SPATIALITE_AVAILABLE
|
||||
from pyrate.common.testing.strategies.geometry import location_types
|
||||
from pyrate.common.testing.strategies.geometry import polar_locations
|
||||
from pyrate.common.testing.strategies.geometry import polar_objects
|
||||
from pyrate.common.testing.strategies.geometry import polar_polygons
|
||||
from pyrate.common.testing.strategies.geometry import polar_routes_stable
|
||||
|
||||
|
||||
# force testing this in CI to make sure it is tested regularly at least there
|
||||
SKIP_IF_SPATIALITE_IS_MISSING = skipIf(
|
||||
not SPATIALITE_AVAILABLE and not IS_CI, "allow spatialite to be missing and skip the tests in that case"
|
||||
)
|
||||
|
||||
|
||||
# reduce the example count since else this will take way too long, especially on the extended tests
|
||||
TEST_REDUCED_COUNT = settings(
|
||||
max_examples=500 if IS_EXTENDED_TESTING else 50,
|
||||
deadline=1000,
|
||||
suppress_health_check=(HealthCheck.too_slow,),
|
||||
)
|
||||
|
||||
|
||||
@SKIP_IF_SPATIALITE_IS_MISSING
|
||||
class TestDatabase(TestCase):
|
||||
"""Test for basic use of the database."""
|
||||
|
||||
@staticmethod
|
||||
def _apply_id_if_missing(geometry: Geospatial, identifier: Optional[int]) -> None:
|
||||
if geometry.identifier is None:
|
||||
geometry.identifier = identifier
|
||||
|
||||
def test_empty_creation(self) -> None:
|
||||
"""Tests whether the creation of a new database if not crashing anything."""
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
self.assertEqual(len(database), database.count_geometries())
|
||||
self.assertEqual(
|
||||
database.count_geometries(), 0, "a freshly initialized database should contain no polygons"
|
||||
)
|
||||
self.assertEqual(
|
||||
database.count_vertices(), 0, "a freshly initialized database should contain no vertices"
|
||||
)
|
||||
|
||||
def test_disable_issue_create_statement(self) -> None:
|
||||
"""Tests whether initializing with ``issue_create_statement=False`` fails."""
|
||||
with SpatialiteDatabase(":memory:", issue_create_statement=False) as database:
|
||||
with self.assertRaises(sqlite3.OperationalError):
|
||||
database.count_geometries()
|
||||
|
||||
def test_write_invalid_geometry_no_update_exception(self) -> None:
|
||||
"""Tests that an exception is raised if an invalid geometry is attempted to be written.
|
||||
|
||||
This tests the case where ``update=False``.
|
||||
"""
|
||||
with self.assertRaises(ValueError):
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
point = PolarLocation(latitude=-70.2, longitude=+120.444, name="Pointy Point")
|
||||
invalid_geometry = PolarPolygon([point, point, point])
|
||||
database.write_geometry(invalid_geometry, update=False)
|
||||
|
||||
def test_write_invalid_geometry_no_update_suppressed(self) -> None:
|
||||
"""Tests that NO exception is raised if an invalid geometry is attempted to be written.
|
||||
|
||||
This tests the case where ``update=False`` and ``raise_on_failure=False``.
|
||||
"""
|
||||
with self.assertRaises(UserWarning):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error")
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
point = PolarLocation(latitude=-70.2, longitude=+120.444, name="Pointy Point")
|
||||
invalid_geometry = PolarPolygon([point, point, point])
|
||||
database.write_geometry(invalid_geometry, update=False, raise_on_failure=False)
|
||||
|
||||
@skip("SpatialiteDatabase.write_geometry() currently does not detect it when update=True")
|
||||
def test_write_invalid_geometry_with_update_exception(self) -> None:
|
||||
"""Tests that an exception is raised if an invalid geometry is attempted to be written.
|
||||
|
||||
This tests the case where ``update=True``.
|
||||
"""
|
||||
with self.assertRaises(ValueError):
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
point = PolarLocation(latitude=-70.2, longitude=+120.444, name="Pointy Point")
|
||||
invalid_geometry = PolarPolygon([point, point, point])
|
||||
database.write_geometry(invalid_geometry, update=True)
|
||||
|
||||
@skip("SpatialiteDatabase.write_geometry() currently does not detect it when update=True")
|
||||
def test_write_invalid_geometry_with_update_suppressed(self) -> None:
|
||||
"""Tests that NO exception is raised if an invalid geometry is attempted to be written.
|
||||
|
||||
This tests the case where ``update=True`` and ``raise_on_failure=False``.
|
||||
"""
|
||||
with self.assertRaises(UserWarning):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error")
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
point = PolarLocation(latitude=-70.2, longitude=+120.444, name="Pointy Point")
|
||||
invalid_geometry = PolarPolygon([point, point, point])
|
||||
database.write_geometry(invalid_geometry, update=True, raise_on_failure=False)
|
||||
|
||||
def test_convert_invalid_geometry_type(self) -> None:
|
||||
"""Tests whether converting an unsupported geometry type raises a :class:`NotImplementedError`."""
|
||||
with self.assertRaises(NotImplementedError):
|
||||
# This obviously is a faulty cast, but we need it to trigger the exception
|
||||
polar = cast(PolarLocation, CartesianLocation(55, 55))
|
||||
to_wkb(polar)
|
||||
|
||||
def test_create_twice(self) -> None:
|
||||
"""Tests that opening/creating/initializing a database twice does not cause any problems.
|
||||
|
||||
This method checks for output on stdout and stderr since sqlite will sometimes just print some
|
||||
warnings instead of raising exceptions. This is a regression test.
|
||||
"""
|
||||
# this creates as shared database (within this process); need to pass uri=True later on
|
||||
uri = "file::memory:?cache=shared"
|
||||
|
||||
# capture stdout & stderr
|
||||
with patch("sys.stdout", new=StringIO()) as fake_stdout:
|
||||
with patch("sys.stderr", new=StringIO()) as fake_stderr:
|
||||
# open two databases
|
||||
with SpatialiteDatabase(uri, uri=True):
|
||||
with SpatialiteDatabase(uri, uri=True):
|
||||
pass
|
||||
|
||||
# assert that nothing got printed
|
||||
self.assertEqual(len(fake_stdout.getvalue()), 0)
|
||||
self.assertEqual(len(fake_stderr.getvalue()), 0)
|
||||
|
||||
def test_clear_and_count(self) -> None:
|
||||
"""Tests :meth:`~.SpatialiteDatabase.clear` and the two counting methods."""
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
self.assertEqual(len(database), 0)
|
||||
self.assertEqual(database.count_vertices(), 0)
|
||||
|
||||
poly = PolarPolygon([PolarLocation(0, 0), PolarLocation(0, 1), PolarLocation(1, 1)])
|
||||
|
||||
poly.identifier = 1
|
||||
database.write_geometry(poly)
|
||||
|
||||
self.assertEqual(len(database), 1)
|
||||
self.assertEqual(database.count_vertices(), len(poly.locations))
|
||||
|
||||
poly.identifier = 1
|
||||
database.write_geometry(poly, update=True)
|
||||
|
||||
self.assertEqual(len(database), 1)
|
||||
self.assertEqual(database.count_vertices(), len(poly.locations))
|
||||
|
||||
poly.identifier = 2
|
||||
database.write_geometry(poly)
|
||||
|
||||
self.assertEqual(len(database), 2)
|
||||
self.assertEqual(database.count_vertices(), len(poly.locations) * 2)
|
||||
|
||||
database.clear()
|
||||
|
||||
self.assertEqual(len(database), 0)
|
||||
self.assertEqual(database.count_vertices(), 0)
|
||||
|
||||
def test_result_multi_geometry(self) -> None:
|
||||
"""Tests whether the DB can correctly handle query results that are multi-polygons/-routes."""
|
||||
|
||||
# Test with both routes and polygons
|
||||
for geometry_type in (PolarRoute, PolarPolygon):
|
||||
with self.subTest(f"With type {geometry_type.__name__}"):
|
||||
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
horseshoe = numpy.array(
|
||||
[
|
||||
[-3.06913376, 47.50722936],
|
||||
[-3.0893898, 47.52566325],
|
||||
[-3.07788849, 47.54640812],
|
||||
[-3.03050995, 47.55278059],
|
||||
[-2.9875946, 47.54675573],
|
||||
[-2.97849655, 47.53006788],
|
||||
[-2.97712326, 47.51801223],
|
||||
[-2.97849655, 47.50908464],
|
||||
[-3.04887772, 47.50653362],
|
||||
[-3.04922104, 47.51047605],
|
||||
[-2.9898262, 47.51349065],
|
||||
[-2.99480438, 47.54084606],
|
||||
[-3.03136826, 47.54698747],
|
||||
[-3.06947708, 47.54327953],
|
||||
[-3.07806015, 47.52763379],
|
||||
[-3.06741714, 47.51198337],
|
||||
[-3.06913376, 47.50722936],
|
||||
]
|
||||
)
|
||||
touch_point = PolarLocation(longitude=-3.0588340759277344, latitude=47.50943249496333)
|
||||
|
||||
database.write_geometry(geometry_type.from_numpy(horseshoe)) # type: ignore
|
||||
result = list(database.read_geometries_around(touch_point, radius=3_000))
|
||||
self.assertTrue(len(result) in {2, 3})
|
||||
|
||||
def _random_insert_and_extract_all_generic(
|
||||
self, geometry: PolarGeometry, location_type: LocationType, update: bool
|
||||
) -> None:
|
||||
"""Tests whether inserting and then reading works in a very basic setting."""
|
||||
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
# it should be empty in the beginning
|
||||
self.assertEqual(0, len(database))
|
||||
self.assertEqual(0, database.count_geometries())
|
||||
self.assertEqual(0, database.count_vertices())
|
||||
|
||||
# insert the polygon
|
||||
try:
|
||||
database.write_geometry(geometry, update=update)
|
||||
except ValueError:
|
||||
return # this example is corrupt, try the next one
|
||||
else:
|
||||
if update and len(database) == 0: # Errors cannot be checked if update==True
|
||||
return # this example is corrupt, try the next one
|
||||
|
||||
# now the database should not be empty anymore
|
||||
self.assertEqual(1, len(database))
|
||||
self.assertEqual(1, database.count_geometries())
|
||||
|
||||
if isinstance(geometry, (PolarRoute, PolarPolygon)):
|
||||
# Some repeated points might be removed, so we cannot check the exact number of vertices
|
||||
self.assertGreaterEqual(len(geometry.locations), database.count_vertices())
|
||||
else: # is a PolarLocation
|
||||
self.assertEqual(1, database.count_vertices())
|
||||
|
||||
# the element should be included in "all"
|
||||
read_obstacles = list(database.read_all())
|
||||
self.assertEqual(1, len(read_obstacles))
|
||||
|
||||
# it should only be included if the type matches
|
||||
all_filtered = list(database.read_all(only_location_type=location_type))
|
||||
if geometry.location_type == location_type:
|
||||
self.assertEqual(all_filtered, read_obstacles)
|
||||
else:
|
||||
self.assertEqual(len(all_filtered), 0)
|
||||
|
||||
# and it should be the one that we have written into the database in the first place
|
||||
read_obstacles_single = read_obstacles[0]
|
||||
# the id may be newly generated if polygon has the id None, so
|
||||
# set it to the generated one for the sake of equality testing
|
||||
TestDatabase._apply_id_if_missing(geometry, read_obstacles_single.identifier)
|
||||
|
||||
assert isinstance(read_obstacles_single, type(geometry)) # Make mypy understand this check
|
||||
|
||||
if isinstance(geometry, PolarPolygon):
|
||||
self.assertTrue(geometry.almost_congruent(read_obstacles_single)) # type: ignore
|
||||
else:
|
||||
self.assertTrue(geometry.equals_exact(read_obstacles_single, tolerance=1e-3))
|
||||
|
||||
@given(polar_locations(), location_types(), st.booleans())
|
||||
@TEST_REDUCED_COUNT
|
||||
def test_random_insert_and_extract_all_locations(
|
||||
self, geometry: PolarGeometry, location_type: LocationType, update: bool
|
||||
) -> None:
|
||||
"""Basic test with locations."""
|
||||
self._random_insert_and_extract_all_generic(geometry, location_type, update)
|
||||
|
||||
@given(polar_routes_stable(), location_types(), st.booleans())
|
||||
@TEST_REDUCED_COUNT
|
||||
def test_random_insert_and_extract_all_routes(
|
||||
self, geometry: PolarGeometry, location_type: LocationType, update: bool
|
||||
) -> None:
|
||||
"""Basic test with routes."""
|
||||
self._random_insert_and_extract_all_generic(geometry, location_type, update)
|
||||
|
||||
@given(polar_polygons(), location_types(), st.booleans())
|
||||
@TEST_REDUCED_COUNT
|
||||
def test_random_insert_and_extract_all_polygons(
|
||||
self, geometry: PolarGeometry, location_type: LocationType, update: bool
|
||||
) -> None:
|
||||
"""Basic test with polygons."""
|
||||
self._random_insert_and_extract_all_generic(geometry, location_type, update)
|
||||
|
||||
def test_copy_to_other_database(self) -> None:
|
||||
"""Tests whether database can be copied.
|
||||
|
||||
This test is not performed using hypothesis as it takes too long.
|
||||
"""
|
||||
|
||||
location_1 = PolarLocation(latitude=-76.400, longitude=-171.924)
|
||||
location_2 = PolarLocation(latitude=-70.400, longitude=-171.924)
|
||||
location_3 = PolarLocation(latitude=-76.400, longitude=-170.924)
|
||||
polygons = [
|
||||
PolarPolygon(
|
||||
locations=[location_1, location_2, location_3],
|
||||
name="K",
|
||||
identifier=1234145,
|
||||
location_type=LocationType.SHALLOW_WATER,
|
||||
),
|
||||
PolarPolygon(locations=[location_1, location_2, location_3], identifier=2342),
|
||||
]
|
||||
|
||||
with TemporaryDirectory() as directory_name:
|
||||
database_file_name = join(directory_name, "other_db.sqlite")
|
||||
|
||||
with SpatialiteDatabase(":memory:") as first_database:
|
||||
with first_database.disable_synchronization():
|
||||
first_database.write_geometries(polygons)
|
||||
first_database.copy_contents_to_database(database_file_name)
|
||||
|
||||
with SpatialiteDatabase(database_file_name) as second_database:
|
||||
read = list(second_database.read_all())
|
||||
|
||||
def sorter(geometry: Geospatial) -> int:
|
||||
return geometry.identifier or -1
|
||||
|
||||
read = list(sorted(read, key=sorter))
|
||||
polygons = list(sorted(polygons, key=sorter))
|
||||
|
||||
self.assertEqual(len(read), len(polygons))
|
||||
for polygon_a, polygon_b in zip(read, polygons):
|
||||
assert isinstance(polygon_a, PolarPolygon) # Make mypy understand this check
|
||||
self.assertTrue(polygon_a.equals_almost_congruent(polygon_b, rel_tolerance=1e-15))
|
||||
|
||||
@settings(max_examples=50 if IS_EXTENDED_TESTING else 10, suppress_health_check=(HealthCheck.too_slow,))
|
||||
@given(st.lists(polar_objects(), min_size=0, max_size=3))
|
||||
def test_database_simplification_zero_tolerance(self, geometries: List[PolarGeometry]) -> None:
|
||||
"""Tests whether database objects can be simplified."""
|
||||
|
||||
for index, geometry in enumerate(geometries):
|
||||
geometry.identifier = index
|
||||
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
try:
|
||||
database.write_geometries(geometries)
|
||||
except ValueError:
|
||||
return # this example is corrupt, try the next one
|
||||
database.simplify_contents(0.0)
|
||||
read = list(database.read_all())
|
||||
|
||||
# only one polygon should be returned
|
||||
self.assertEqual(len(read), len(geometries))
|
||||
for original, read_back in zip(geometries, read):
|
||||
self.assertTrue(original.equals_exact(read_back, tolerance=1e-3))
|
||||
|
||||
def test_database_simplification(self) -> None:
|
||||
"""Tests whether database objects can be simplified."""
|
||||
|
||||
# set unique identifiers
|
||||
points = numpy.array(Point(0, 0).buffer(10_000, resolution=16).exterior.coords)
|
||||
cartesian_polygon = CartesianPolygon.from_numpy(points, identifier=10042)
|
||||
polygon = cartesian_polygon.to_polar(origin=PolarLocation(-50.111, -30))
|
||||
self.assertEqual(len(polygon.locations), 65)
|
||||
|
||||
with SpatialiteDatabase(":memory:") as database:
|
||||
database.write_geometry(polygon)
|
||||
database.simplify_contents(100)
|
||||
read = list(database.read_all())
|
||||
|
||||
# only one polygon should be returned
|
||||
self.assertEqual(len(read), 1)
|
||||
read_polygon = read[0]
|
||||
assert isinstance(read_polygon, PolarPolygon) # Make mypy understand this check
|
||||
|
||||
# That polygon should be similar
|
||||
self.assertEqual(33, len(read_polygon.locations))
|
||||
self.assertAlmostEqual(read_polygon.area, polygon.area, places=-3)
|
||||
self.assertTrue(read_polygon.equals_almost_congruent(polygon, rel_tolerance=0.01))
|
||||
|
||||
# else, it should be the same
|
||||
polygon.locations = read_polygon.locations
|
||||
self.assertEqual(polygon, read_polygon)
|
||||
|
||||
|
||||
@SKIP_IF_SPATIALITE_IS_MISSING
|
||||
class TestDatabaseReadAroundHandcrafted(TestCase):
|
||||
"""Tests :meth:`pyrate.common.charts.SpatialiteDatabase.read_obstacles_around` with known examples."""
|
||||
|
||||
included_polygon = PolarPolygon(
|
||||
[PolarLocation(1, 1), PolarLocation(1, -1), PolarLocation(-1, -1), PolarLocation(-1, 1)], identifier=1
|
||||
)
|
||||
excluded_polygon = PolarPolygon(
|
||||
[PolarLocation(56, 170), PolarLocation(56.5, 170), PolarLocation(56, 170.2)], identifier=2
|
||||
)
|
||||
both_polygons = [included_polygon, excluded_polygon]
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.database = SpatialiteDatabase(":memory:")
|
||||
self.database.write_geometries(self.both_polygons)
|
||||
super().setUp()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self.database.close()
|
||||
super().tearDown()
|
||||
|
||||
def test_read_around_includes_full(self) -> None:
|
||||
"""Reads a complete polygon."""
|
||||
|
||||
around = list(self.database.read_geometries_around(PolarLocation(0, 2), radius=500_000))
|
||||
self.assertEqual(1, len(around))
|
||||
self.assertEqual(1, len(around))
|
||||
read = around[0]
|
||||
assert isinstance(read, PolarPolygon) # Make mypy understand this check
|
||||
self.assertTrue(self.included_polygon.almost_congruent(read))
|
||||
|
||||
def test_read_around_includes_nothing(self) -> None:
|
||||
"""Tests that :meth:`pyrate.common.charts.SpatialiteDatabase.read_obstacles_around` works correctly.
|
||||
|
||||
Reads nothing.
|
||||
"""
|
||||
|
||||
around = list(self.database.read_geometries_around(PolarLocation(0, 2), radius=0))
|
||||
self.assertEqual(0, len(around))
|
||||
|
||||
def test_read_around_includes_partial(self) -> None:
|
||||
"""Tests that :meth:`pyrate.common.charts.SpatialiteDatabase.read_obstacles_around` works correctly.
|
||||
|
||||
Reads about half of the polygon.
|
||||
"""
|
||||
query_point = PolarLocation(latitude=0.0, longitude=5.0)
|
||||
# this is the distance to center of self.included_polygon
|
||||
radius = query_point.distance(PolarLocation(0.0, 0.0))
|
||||
read = list(self.database.read_geometries_around(query_point, radius=radius))
|
||||
self.assertEqual(1, len(read))
|
||||
read_polygon = read[0]
|
||||
assert isinstance(read_polygon, PolarPolygon) # Make mypy understand this check
|
||||
|
||||
# these shall only be very roughly similar, as half of the polygon is missing
|
||||
# thus, we allow for a very large relative tolerance
|
||||
self.assertTrue(read_polygon.equals_almost_congruent(self.included_polygon, rel_tolerance=0.6))
|
||||
|
||||
# this is roughly the part that should be included in the result
|
||||
eastern_half = PolarPolygon(
|
||||
[PolarLocation(1, 0), PolarLocation(-1, 0), PolarLocation(-1, 1), PolarLocation(1, 1)]
|
||||
)
|
||||
# thus, we allow for less relative tolerance
|
||||
self.assertTrue(read_polygon.almost_congruent(eastern_half, rel_tolerance=0.15))
|
96
pyrate/tests/common/charts/test_s57_files.py
Normal file
96
pyrate/tests/common/charts/test_s57_files.py
Normal file
@ -0,0 +1,96 @@
|
||||
"""Tests whether ``pyrate.common.charts.raw_files`` correctly handles IHO S-57 chart files."""
|
||||
|
||||
# Python standard
|
||||
from pathlib import Path
|
||||
|
||||
# Testing
|
||||
from unittest import skipIf
|
||||
from unittest import TestCase
|
||||
|
||||
# Extra test tooling
|
||||
import pytest
|
||||
|
||||
# Pyrate library
|
||||
from pyrate.common.testing import IS_CI
|
||||
from pyrate.plan.geometry import LocationType
|
||||
|
||||
# Module under test
|
||||
from pyrate.common.charts import ChartFileHandler
|
||||
from pyrate.common.charts.s57_files import _OSGEO_PRESENT
|
||||
from pyrate.common.charts import S57ChartHandler
|
||||
|
||||
|
||||
PATH_TO_EXAMPLES = Path(__file__).parent / "example_charts"
|
||||
CHARTS = [
|
||||
PATH_TO_EXAMPLES / "nested_folder/US4VA70M/US4VA70M.000",
|
||||
PATH_TO_EXAMPLES / "US1BS04M/US1BS04M.000",
|
||||
PATH_TO_EXAMPLES / "US4AK5GM/US4AK5GM.000",
|
||||
PATH_TO_EXAMPLES / "US4FL87M/US4FL87M.000",
|
||||
]
|
||||
CHARTS.sort()
|
||||
|
||||
|
||||
class TestChartDiscovery(TestCase):
|
||||
"""Tests that charts are correctly discovered"""
|
||||
|
||||
def test_discovery(self):
|
||||
"""Also checks for nested folders and npn-chart files being present"""
|
||||
discovered = list(S57ChartHandler.find_chart_files(PATH_TO_EXAMPLES))
|
||||
discovered.sort()
|
||||
|
||||
# check that exactly the expected charts have been found
|
||||
self.assertListEqual(discovered, CHARTS)
|
||||
|
||||
# check that they have the characteristic file extension
|
||||
for chart_path in discovered:
|
||||
self.assertTrue(chart_path.name.endswith(".000"))
|
||||
|
||||
|
||||
# force testing this in CI to make sure it is tested regularly at least there
|
||||
@skipIf(not _OSGEO_PRESENT and not IS_CI, "allow osgeo to be missing and skip the tests in that case")
|
||||
class TestReadCharts(TestCase):
|
||||
"""Tests whether actually reading the charts works"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.handler: ChartFileHandler = S57ChartHandler()
|
||||
|
||||
def test_reading_non_existent_file(self):
|
||||
"""Tests reading a chart file that does not exist."""
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
# Wrapping this in a list causes the generator/iterator to be actually evaluated
|
||||
list(self.handler.read_chart_file("/does/surely/not/exist/and/if/it/does/we/have/a/troll"))
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
# Wrapping this in a list causes the generator/iterator to be actually evaluated
|
||||
list(self.handler.read_chart_file("/does/surely/not/exist/and/if/it/does/we/have/a/troll.000"))
|
||||
|
||||
def test_reading_wrong_file_type(self):
|
||||
"""Tests reading a chart file that is not an S57 file (this Python program file)."""
|
||||
with self.assertRaises(IOError):
|
||||
# This test python file is not a chart
|
||||
not_a_chart_file = __file__
|
||||
# Wrapping this in a list causes the generator/iterator to be actually evaluated
|
||||
list(self.handler.read_chart_file(not_a_chart_file))
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:Ignoring LineString geometry in chart")
|
||||
def test_reading_contains_all_types(self):
|
||||
"""Checks for specific types of entries in the charts.
|
||||
|
||||
Note:
|
||||
Only tests for Landmasses as of now
|
||||
"""
|
||||
|
||||
all_obstacles = [obstacle for chart in CHARTS for obstacle in self.handler.read_chart_file(chart)]
|
||||
self.assertGreater(len(all_obstacles), 0, "no obstacles were read")
|
||||
|
||||
relevant_types = (
|
||||
(LocationType.LAND, "Landmass"),
|
||||
(LocationType.SHALLOW_WATER, "Depth"),
|
||||
(LocationType.OBSTRUCTION, "Buoy"),
|
||||
)
|
||||
for location_type, name_component in relevant_types:
|
||||
filtered = [
|
||||
o
|
||||
for o in all_obstacles
|
||||
if (o.name is not None and name_component in o.name and location_type == o.location_type)
|
||||
]
|
||||
self.assertTrue(filtered, f"no obstacle of type {name_component} was found")
|
1
pyrate/tests/common/math/__init__.py
Normal file
1
pyrate/tests/common/math/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Tests ``pyrate.common.math.**``."""
|
Binary file not shown.
6
pyrate/tests/common/raster_datasets/__init__.py
Normal file
6
pyrate/tests/common/raster_datasets/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
"""Tests the raster datasets.
|
||||
|
||||
The test file ``Earth2014.TBI2014.30min.geod.geo.tif`` is the *Earth 2014* dataset, exported from the
|
||||
`data repository
|
||||
<https://gitlab.sailingteam.hg.tu-darmstadt.de/informatik/data/-/tree/master/topography/earth2014>`__.
|
||||
"""
|
201
pyrate/tests/common/raster_datasets/test_geo_datasets.py
Normal file
201
pyrate/tests/common/raster_datasets/test_geo_datasets.py
Normal file
@ -0,0 +1,201 @@
|
||||
"""Tests :class:`pyrate.common.raster_datasets.geo_datasets.DataSetAccess`."""
|
||||
|
||||
# Standard library
|
||||
from math import degrees
|
||||
from math import pi
|
||||
from math import radians
|
||||
|
||||
# Generic testing
|
||||
from unittest import TestCase
|
||||
|
||||
# Geometry
|
||||
from rasterio.windows import intersect
|
||||
|
||||
# Hypothesis testing
|
||||
from hypothesis import given
|
||||
import hypothesis.strategies as st
|
||||
|
||||
# Numeric testing
|
||||
from numpy import rad2deg
|
||||
from numpy.testing import assert_array_almost_equal
|
||||
|
||||
# Own Geometry
|
||||
from pyrate.plan.geometry.helpers import meters2rad
|
||||
from pyrate.plan.geometry.helpers import rad2meters
|
||||
from pyrate.plan.geometry import PolarLocation
|
||||
|
||||
# Test environment helper
|
||||
from ... import _open_test_geo_dataset
|
||||
|
||||
|
||||
class TestGeoDataset(TestCase):
|
||||
"""Ensure that the :class:`pyrate.plan.graph.generate.geo_datasets.DataSetAccess` works correctly.
|
||||
|
||||
Uses the *Earth2014* dataset.
|
||||
"""
|
||||
|
||||
#: The resolution of the dataset in arc-minutes
|
||||
DATASET_RESOLUTION = 30
|
||||
#: The maximal distance of two data points in the dataset in degrees
|
||||
MAX_POINT_DISTANCE_DEG = DATASET_RESOLUTION / 60
|
||||
#: The maximal distance of two data points in the dataset in meters (at the equator)
|
||||
MAX_POINT_DISTANCE = rad2meters(radians(MAX_POINT_DISTANCE_DEG))
|
||||
|
||||
# Handle the context manager, see https://stackoverflow.com/a/11180583/3753684
|
||||
def run(self, result=None) -> None:
|
||||
with _open_test_geo_dataset() as dataset:
|
||||
self.dataset = dataset # pylint: disable=attribute-defined-outside-init
|
||||
super().run(result)
|
||||
|
||||
@given(
|
||||
st.floats(min_value=-pi / 2 * 0.75, max_value=+pi / 2 * 0.75),
|
||||
st.floats(min_value=-pi * 0.75, max_value=+pi * 0.75),
|
||||
st.floats(min_value=0.001, max_value=1000_000.0),
|
||||
)
|
||||
def test_bounding_window_center_of_dataset(
|
||||
self, latitude: float, longitude: float, radius: float
|
||||
) -> None:
|
||||
"""Tests that the bounding box is correctly calculated if the query point is not at the border."""
|
||||
# pylint: disable=too-many-locals
|
||||
|
||||
win_1, win_2 = self.dataset.get_bounding_windows_around(latitude, longitude, radius)
|
||||
|
||||
self.assertIsNone(win_2, "only one window shall be returned")
|
||||
|
||||
# Get the geographical extends in degrees, not radians:
|
||||
left, bottom, right, top = self.dataset.dataset.window_bounds(win_1)
|
||||
|
||||
# Check the position of the window
|
||||
latitude_deg, longitude_deg = degrees(latitude), degrees(longitude)
|
||||
|
||||
self.assertLessEqual(bottom, latitude_deg + 1e-12)
|
||||
self.assertGreaterEqual(top, latitude_deg - 1e-12)
|
||||
self.assertAlmostEqual(
|
||||
(top + bottom) / 2,
|
||||
latitude_deg,
|
||||
delta=self.MAX_POINT_DISTANCE_DEG,
|
||||
msg="window should be vertically centered around the given center point",
|
||||
)
|
||||
|
||||
self.assertLessEqual(left, longitude_deg + 1e-12)
|
||||
self.assertGreaterEqual(right, longitude_deg - 1e-12)
|
||||
self.assertAlmostEqual(
|
||||
(right + left) / 2,
|
||||
longitude_deg,
|
||||
delta=self.MAX_POINT_DISTANCE_DEG,
|
||||
msg="window should be horizontally centered around the given center point",
|
||||
)
|
||||
|
||||
# Check the size of the window
|
||||
self.assertLessEqual(left, right)
|
||||
self.assertLessEqual(bottom, top)
|
||||
|
||||
# Distances are uniform along longitudes
|
||||
radius_deg = degrees(meters2rad(radius))
|
||||
self.assertGreaterEqual(top - bottom, 2 * radius_deg - 1e-12)
|
||||
self.assertLessEqual(top - bottom, 2 * radius_deg + 3 * self.MAX_POINT_DISTANCE_DEG)
|
||||
|
||||
# Distances are more complicated along the latitudes
|
||||
left_side_center = PolarLocation(latitude=(top + bottom) / 2, longitude=left)
|
||||
right_side_center = PolarLocation(latitude=(top + bottom) / 2, longitude=right)
|
||||
# Use approximate=True for a spherical model
|
||||
distance_horizontal = left_side_center.distance(right_side_center, approximate=True)
|
||||
# The rough checking of the bounding boxes is very coarse and was determined by fiddling until it
|
||||
# works
|
||||
# This part of the test guarantees that the windows is roughly the right size, but pinning it down to
|
||||
# exact number is hard since we round the discrete window bounds, map them to geographical coordinates
|
||||
# and then have to deal with floating point inaccuracies
|
||||
self.assertGreaterEqual(distance_horizontal, 2 * radius - 6 * self.MAX_POINT_DISTANCE)
|
||||
self.assertLessEqual(distance_horizontal, 2 * radius + 4 * self.MAX_POINT_DISTANCE)
|
||||
|
||||
@given(
|
||||
st.floats(min_value=-pi / 2 * 0.95, max_value=+pi / 2 * 0.95),
|
||||
st.one_of(
|
||||
[st.floats(min_value=-pi, max_value=-pi * 0.995), st.floats(min_value=+pi * 0.995, max_value=+pi)]
|
||||
),
|
||||
st.floats(min_value=200_000.0, max_value=1_000_000.0),
|
||||
)
|
||||
def test_bounding_window_left_and_right_side(
|
||||
self, latitude: float, longitude: float, radius: float
|
||||
) -> None:
|
||||
"""Tests that the bounding box is correctly calculated if the query point is at the border.
|
||||
|
||||
Very high latitudes (near the poles) are not tested as there might be a single (albeit very wide)
|
||||
window being returned. For the same reason, only moderate radii are tested.
|
||||
"""
|
||||
window_1, window_2 = self.dataset.get_bounding_windows_around(latitude, longitude, radius)
|
||||
|
||||
# We need a plain assert here for type checking
|
||||
assert window_2 is not None, "two windows should be returned"
|
||||
self.assertFalse(intersect(window_1, window_2), "windows may never overlap")
|
||||
|
||||
# Also test the same as in :meth:`~test_bounding_window_intersection_empty`
|
||||
self.assertEqual(window_1.height, window_2.height)
|
||||
self.assertGreaterEqual(window_1.height, 1)
|
||||
self.assertGreaterEqual(window_1.width, 1)
|
||||
self.assertGreaterEqual(window_2.width, 1)
|
||||
self.assertLessEqual(window_1.height, self.dataset.dataset.height)
|
||||
self.assertLessEqual(window_1.width + window_2.width, self.dataset.dataset.width)
|
||||
|
||||
@given(
|
||||
st.floats(min_value=-pi / 2, max_value=+pi / 2),
|
||||
st.floats(min_value=-pi, max_value=+pi),
|
||||
st.floats(min_value=0.001, max_value=100_000_000.0),
|
||||
)
|
||||
def test_bounding_window_general_properties(
|
||||
self, latitude: float, longitude: float, radius: float
|
||||
) -> None:
|
||||
"""Tests some more general properties that should hold for all windows and window pairs.
|
||||
|
||||
In particular, it makes sure that even if a window pair is very wide, the intersection is always
|
||||
empty.
|
||||
"""
|
||||
window_1, window_2 = self.dataset.get_bounding_windows_around(latitude, longitude, radius)
|
||||
|
||||
# Make sure that everything in window_1 is rounded
|
||||
self.assertIsInstance(window_1.col_off, int)
|
||||
self.assertIsInstance(window_1.row_off, int)
|
||||
self.assertIsInstance(window_1.height, int)
|
||||
self.assertIsInstance(window_1.width, int)
|
||||
|
||||
# Test some general properties of window_1
|
||||
self.assertTrue(radius == 0 or window_1.height >= 1)
|
||||
self.assertLessEqual(window_1.height, self.dataset.dataset.height)
|
||||
self.assertTrue(radius == 0 or window_1.width >= 1)
|
||||
self.assertLessEqual(window_1.width, self.dataset.dataset.width)
|
||||
|
||||
if window_2 is not None:
|
||||
self.assertGreater(radius, 0)
|
||||
|
||||
# Make sure that everything in window_2 is rounded
|
||||
self.assertIsInstance(window_2.col_off, int)
|
||||
self.assertIsInstance(window_2.row_off, int)
|
||||
self.assertIsInstance(window_2.height, int)
|
||||
self.assertIsInstance(window_2.width, int)
|
||||
|
||||
# Test some general properties of window_2 in relation to window_1
|
||||
self.assertEqual(window_1.height, window_2.height)
|
||||
self.assertGreaterEqual(window_2.width, 1)
|
||||
self.assertLessEqual(window_1.width + window_2.width, self.dataset.dataset.width)
|
||||
|
||||
self.assertFalse(intersect(window_1, window_2), "windows may never overlap")
|
||||
|
||||
@given(
|
||||
st.floats(min_value=-pi / 2 * 0.75, max_value=+pi / 2 * 0.75),
|
||||
st.floats(min_value=-pi * 0.75, max_value=+pi * 0.75),
|
||||
st.floats(min_value=0.001, max_value=1000_000.0),
|
||||
)
|
||||
def test_meshgrid_generation(self, latitude: float, longitude: float, radius: float) -> None:
|
||||
"""Tests that msehgrids are generated correctly no matter whether radians are used or not.
|
||||
|
||||
Uses the data generation of :meth:`~test_bounding_window_center_of_dataset`.
|
||||
"""
|
||||
|
||||
window, window_empty = self.dataset.get_bounding_windows_around(latitude, longitude, radius)
|
||||
self.assertIsNone(window_empty, "only one window shall be returned")
|
||||
|
||||
lats_deg, lons_deg = self.dataset.lat_lon_meshgrid_for(window, window_empty, radians=False)
|
||||
lats_rad, lons_rad = self.dataset.lat_lon_meshgrid_for(window, window_empty, radians=True)
|
||||
|
||||
assert_array_almost_equal(rad2deg(lats_rad), lats_deg)
|
||||
assert_array_almost_equal(rad2deg(lons_rad), lons_deg)
|
132
pyrate/tests/common/raster_datasets/test_transformers.py
Normal file
132
pyrate/tests/common/raster_datasets/test_transformers.py
Normal file
@ -0,0 +1,132 @@
|
||||
"""
|
||||
Tests the transformers in :mod:`pyrate.common.raster_datasets.transformer_base` and in
|
||||
:mod:`pyrate.common.raster_datasets.transformers_concrete`.
|
||||
"""
|
||||
|
||||
# Testing
|
||||
from unittest import TestCase
|
||||
|
||||
# Scientific
|
||||
from numpy import array
|
||||
from numpy import empty
|
||||
from numpy import float32
|
||||
from numpy import int16
|
||||
from numpy.testing import assert_array_equal
|
||||
from numpy import uint16
|
||||
from numpy import uint32
|
||||
from pandas import DataFrame
|
||||
from pandas import Series
|
||||
from pandas.testing import assert_frame_equal
|
||||
from pandas.testing import assert_series_equal
|
||||
|
||||
# Module under test
|
||||
from pyrate.common.raster_datasets.transformers_concrete import BathymetricTransformer
|
||||
from pyrate.common.raster_datasets.transformers_concrete import ConstantTransformer
|
||||
|
||||
# Graph generation
|
||||
from pyrate.plan.graph import create_earth_graph
|
||||
from pyrate.plan.graph import GeoNavigationGraph
|
||||
from pyrate.plan.graph import min_required_frequency
|
||||
|
||||
# CI/Testing helpers
|
||||
from ... import _open_test_geo_dataset
|
||||
|
||||
|
||||
class TestGetNodePropertiesWithConstantTransformer(TestCase):
|
||||
"""Ensure that the :meth:`pyrate.plan.graph.GeoNavigationGraph.append_properties` works correctly."""
|
||||
|
||||
def test_get_node_properties_empty_coordinates(self) -> None:
|
||||
"""Tests getting properties for a graph without nodes."""
|
||||
graph = GeoNavigationGraph.from_coordinates_degrees(
|
||||
latitudes=empty((0,)), longitudes=empty((0,)), edges=empty((0, 2)), node_radius=111.111
|
||||
)
|
||||
transformers = [ConstantTransformer(42, uint32, "prop_1"), ConstantTransformer(43, uint16, "prop_2")]
|
||||
graph.append_properties(transformers)
|
||||
self.assertEqual(len(graph.node_properties), 0)
|
||||
assert_array_equal(graph.node_properties.columns, ["prop_1", "prop_2"])
|
||||
|
||||
def test_get_node_properties_no_transformers(self) -> None:
|
||||
"""Tests getting properties without a transformer."""
|
||||
graph = GeoNavigationGraph.from_coordinates_degrees(
|
||||
latitudes=array([0, 1]), longitudes=array([0, 0]), edges=array([[0, 1]]), node_radius=111.111
|
||||
)
|
||||
graph.append_properties([]) # empty!
|
||||
self.assertEqual(len(graph.node_properties), 2)
|
||||
assert_array_equal(graph.node_properties.columns, [])
|
||||
|
||||
def test_get_node_properties_single_transformer(self) -> None:
|
||||
"""Tests getting properties using only a single transformer."""
|
||||
graph = GeoNavigationGraph.from_coordinates_degrees(
|
||||
latitudes=array([0, 1]),
|
||||
longitudes=array([0, 0]),
|
||||
edges=array([[0, 1]]),
|
||||
node_radius=0.0, # some weird radius
|
||||
)
|
||||
# now we use `append_property` to append a single one
|
||||
graph.append_property(ConstantTransformer(33, uint32, "prop_1"))
|
||||
self.assertEqual(len(graph.node_properties), 2)
|
||||
assert_frame_equal(graph.node_properties, DataFrame(data={"prop_1": [33, 33]}, dtype=uint32))
|
||||
|
||||
def test_get_node_properties_single_transformer_str_datatype(self) -> None:
|
||||
"""Tests getting properties using only a single transformer and a string datatype."""
|
||||
graph = GeoNavigationGraph.from_coordinates_degrees(
|
||||
latitudes=array([0]),
|
||||
longitudes=array([0]),
|
||||
edges=array([[0, 0]]), # edge to itself
|
||||
node_radius=111.111,
|
||||
)
|
||||
# now we use `append_property` to append a single one
|
||||
data_type = "U10" # must give string data type explicitly and not with np.str or "U"
|
||||
graph.append_property(ConstantTransformer("content", data_type, "prop_1"))
|
||||
self.assertEqual(len(graph.node_properties), 1)
|
||||
assert_frame_equal(graph.node_properties, DataFrame(data={"prop_1": ["content"]}, dtype=data_type))
|
||||
|
||||
def test_get_node_properties_multiple_transformers(self) -> None:
|
||||
"""Tests getting properties using multiple transformers."""
|
||||
graph = GeoNavigationGraph.from_coordinates_degrees(
|
||||
latitudes=array([0, 1]), longitudes=array([0, 0]), edges=array([[0, 1]]), node_radius=111.111
|
||||
)
|
||||
# now we use `append_property` to append a single one
|
||||
graph.append_properties(
|
||||
[ConstantTransformer(33, uint32, "prop_1"), ConstantTransformer(99, int16, "prop_2")]
|
||||
)
|
||||
self.assertEqual(len(graph.node_properties), 2)
|
||||
assert_array_equal(graph.node_properties.columns, ["prop_1", "prop_2"])
|
||||
assert_series_equal(
|
||||
graph.node_properties["prop_1"], Series(data=[33, 33], dtype=uint32, name="prop_1")
|
||||
)
|
||||
assert_series_equal(
|
||||
graph.node_properties["prop_2"], Series(data=[99, 99], dtype=int16, name="prop_2")
|
||||
)
|
||||
|
||||
|
||||
class TestBathymetricTransformer(TestCase):
|
||||
"""Tests :class:`pyrate.common.raster_datasets.transformers_concrete.BathymetricTransformer`."""
|
||||
|
||||
def test_all_modes(self) -> None:
|
||||
"""Tests all modes at once."""
|
||||
|
||||
# create a coarse grid
|
||||
distance_meters = 1000_000
|
||||
graph = create_earth_graph(min_required_frequency(distance_meters, in_meters=True))
|
||||
|
||||
# fetch properties
|
||||
modes = list(BathymetricTransformer.Modes)
|
||||
graph.append_property(BathymetricTransformer(_open_test_geo_dataset(), modes))
|
||||
properties = graph.node_properties
|
||||
|
||||
# check that the returned properties are all floats
|
||||
self.assertTrue((properties.dtypes == float32).all())
|
||||
|
||||
def test_no_data(self) -> None:
|
||||
"""Tests that querying for data where there are no data points in the result range raises an error."""
|
||||
for mode in list(BathymetricTransformer.Modes):
|
||||
with self.subTest(mode.name), self.assertRaises(ValueError):
|
||||
with BathymetricTransformer(_open_test_geo_dataset(), [mode]) as transformer:
|
||||
# This works by querying for a point (at 1e-3°N 1e-3°E), where there is no data point
|
||||
# within 1e-9 meters in the underlying dataset
|
||||
# This should trigger an exception (e.g. because the average depth over zero data
|
||||
# points is not clearly)
|
||||
transformer.get_transformed_at_nodes(
|
||||
latitudes=array([1e-3]), longitudes=array([1e-3]), radius=1e-9
|
||||
)
|
Reference in New Issue
Block a user