Skip to content

Commit

Permalink
Merge pull request #183 from capstone-coal/ISSUE-148
Browse files Browse the repository at this point in the history
ISSUE-148 Add option to burn features from multiple vectors onto raster
  • Loading branch information
theoilie authored Nov 27, 2019
2 parents c685b4d + 07ccb18 commit 34a97fa
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 118 deletions.
15 changes: 12 additions & 3 deletions examples/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@
# Set to None to classify the entire image.
# Only applies to example_mineral.py
# For reference, the small image has the shape 931X339 (931 rows and 339
# columns)
MINERAL_SUBSET_ROWS = None #[0, 75]
MINERAL_SUBSET_COLS = None #[0, 75]
# columns). This would translate to [0, 931] rows and [0, 339] columns below
MINERAL_SUBSET_ROWS = None
MINERAL_SUBSET_COLS = None

# Paths to the flowlines of streams and whatever other hydrography data
# should be correlated with a mining classified image.
# Note that the path should be relative to where you're running the
# examples from. These defaults assume that you're running
# `python3 example_environment.py` from the root project directory.
ENVIRONMENT_VECTOR_PATHS = ["pycoal/tests/images/NHDFlowline_cut.shp",
"pycoal/tests/images/GRanD_dams_v1_1.shp",
"pycoal/tests/images/GRanD_reservoirs_v1_1.shp"]
33 changes: 18 additions & 15 deletions examples/example_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,22 @@
from pycoal import environment


def run_environment(mining_filename, vector_filename, correlation_filename):
def run_environment(mining_filename, vector_filenames, correlation_filename):
"""Run environment correlation.
:param mining_filename: Input mining classified file to be processed
:param vector_filename: Path to hydrography data
:param mining_filename: Input mining classified file to be processed
:param vector_filenames: Path(s) to hydrography data
:param correlation_filename: Output environmental correlation image
"""

# create a new environmental correlation instance
environmental_correlation = environment.EnvironmentalCorrelation()

# generate an environmental correlation image of mining
# pixels within 10 meters of a stream
# pixels within 10 meters of a stream/dam/reservoir
environmental_correlation.intersect_proximity(mining_filename,
vector_filename, 10.0,
vector_filenames,
10.0,
correlation_filename)


Expand Down Expand Up @@ -109,29 +110,31 @@ def main(argv=None):
help="Input mining classified file to be "
"processed [default: " +
constants.INPUT_NAME + "_class_mining.hdr]")
parser.add_argument("-hy", "--hydrography", dest="vector_filename",
default='Shape/NHDFlowline.shp',
help="Path to hydrography data [default: "
"Shape/NHDFlowline.shp]")
parser.add_argument("-hy", "--hydrography", dest="vector_filenames",
default=constants.ENVIRONMENT_VECTOR_PATHS,
help="Paths array to hydrography data [default: "
"[pycoal/tests/images/NHDFlowline_cut.shp]]")
parser.add_argument("-e", "--environment", dest="correlation_filename",
default=constants.INPUT_NAME +
"_class_mining_NHDFlowline_correlation.hdr",
"_class_mining_environmental_correlation.hdr",
help="Output environmental correlation image ["
"default: " + constants.INPUT_NAME +
"_class_mining_NHDFlowline_correlation.hdr]")
"_class_mining_environmental_correlation.hdr]")

# Process arguments
args = parser.parse_args(
['-m', constants.INPUT_NAME + "_class_mining.hdr", '-hy',
'Shape/NHDFlowline.shp', '-e',
constants.ENVIRONMENT_VECTOR_PATHS, '-e',
constants.INPUT_NAME +
"_class_mining_NHDFlowline_correlation.hdr"])
"_class_mining_environmental_correlation.hdr"])

mining_filename = args.mining_filename
vector_filename = args.vector_filename
vector_filenames = args.vector_filenames
correlation_filename = args.correlation_filename

run_environment(mining_filename, vector_filename, correlation_filename)
run_environment(mining_filename,
vector_filenames,
correlation_filename)

except KeyboardInterrupt:
return 0
Expand Down
15 changes: 6 additions & 9 deletions examples/example_mining.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
Classification
API filters mineral classified images to identify specific classes of
interest,
by default proxies for coal mining in the USGS Digital Spectral Library 06.
by default proxies for coal mining in the USGS Digital Spectral Library 07.
More reading an this example can be seen at
https://capstone-coal.github.io/docs#usage
Expand Down Expand Up @@ -54,20 +54,18 @@
# path to save mining classified image
mining_filename = "ang20150420t182050_corr_v1e_img_class_mining.hdr"
#Spectral Library Verison Number, Change to 7 if you want to use USGS
Spectral Library Version 7
#Spectral Library Version Number - default USGS Spectral Library Version 7
'''


def run_mining(mineral_filename=constants.INPUT_NAME + "_class.hdr",
mining_filename=constants.INPUT_NAME + "_mining.hdr",
spectral_version="6"):
spectral_version="7"):
"""Run mining classification.
:param mineral_filename: The name of the mineral file
:param mining_filename: The name of the mining file
:param spectral_version: 6 by default. Use 7 if you want to use USGS
Spectral Library Version 7
:param spectral_version: version of Spectral library - 7 by default
"""

# create a new mining classification instance
Expand Down Expand Up @@ -127,14 +125,13 @@ def main(argv=None): # IGNORE:C0111
"default: " + constants.INPUT_NAME +
"_class_mining.hdr]")
parser.add_argument("-v", "--spectral_version",
dest="spectral_version", default='6',
dest="spectral_version", default='7',
help="USGS Spectral Library Version Number")

# Process arguments
args = parser.parse_args(
['-mi', constants.INPUT_NAME + "_class.hdr", '-mo',
constants.INPUT_NAME + "_class_mining.hdr", '-v', '6'])
# args = parser.parse_args()
constants.INPUT_NAME + "_class_mining.hdr", '-v', '7'])

mineral_filename = args.input
mining_filename = args.output
Expand Down
67 changes: 34 additions & 33 deletions pycoal/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self):
"specification: ")

@staticmethod
def intersect_proximity(mining_filename, vector_filename, proximity,
def intersect_proximity(mining_filename, vector_filenames, proximity,
correlated_filename):
"""
Generate an environmental correlation image containing pixels from the
Expand All @@ -45,43 +45,23 @@ def intersect_proximity(mining_filename, vector_filename, proximity,
Args:
mining_filename (str): filename of the mining classified image
vector_filename (str): filename of vector layer
vector_filenames (str[]): filename(s) of vector layer(s)
proximity (float): distance in meters
correlated_filename (str): filename of the correlated image
"""
start = time.time()
logging.info(
"Starting Environmental Correlation for mining image '%s', "
"with vector layer '%s' and proximity distance of '%s' meters.",
mining_filename, vector_filename, proximity)
mining_filename, vector_filenames, proximity)
# get path and file names
output_directory = dirname(abspath(correlated_filename))
mining_name = splitext(basename(abspath(mining_filename)))[0]
vector_name = splitext(basename(abspath(vector_filename)))[0]

# rasterize the vector features to the same dimensions as the mining
# image
feature_header_name = output_directory + '/' + mining_name + '_' +\
vector_name + '.hdr'
EnvironmentalCorrelation.create_empty_copy(mining_filename,
feature_header_name)
feature_image_name = feature_header_name[:-4] + '.img'
EnvironmentalCorrelation.rasterize(vector_filename, feature_image_name)

# generate a proximity map from the features
proximity_header_name = output_directory + '/' + mining_name + '_' +\
vector_name + '_proximity.hdr'
proximity_image_name = proximity_header_name[:-4] + '.img'
EnvironmentalCorrelation.proximity(feature_image_name,
proximity_image_name)

# load mining and proximity images and initialize environmental
# correlation array

# load mining image and initialize environmental correlation array
mining_image = spectral.open_image(mining_filename)
proximity_image = spectral.open_image(proximity_header_name)
correlated_image = numpy.zeros(shape=mining_image.shape,
dtype=numpy.uint16)

# get average pixel size
if mining_image.metadata.get('map info')[10][-6:].lower() == 'meters':
x_pixel_size = float(mining_image.metadata.get('map info')[5])
Expand All @@ -90,14 +70,35 @@ def intersect_proximity(mining_filename, vector_filename, proximity,
else:
raise ValueError('Mining image units not in meters.')

# intersect features within proximity
for x in range(mining_image.shape[0]):
for y in range(mining_image.shape[1]):
if mining_image[x, y, 0] == 1 \
and proximity_image[x, y, 0] * pixel_size <= proximity:
correlated_image[x, y, 0] = mining_image[x, y, 0]

# save the environmental correlation image
for vector_filename in vector_filenames:
# rasterize the vector features to the same dimensions as the
# mining image
vector_name = splitext(basename(abspath(vector_filename)))[0]
feature_header_name = output_directory + '/' + mining_name + \
'_' + vector_name + '.hdr'
EnvironmentalCorrelation.create_empty_copy(mining_filename,
feature_header_name)
feature_image_name = feature_header_name[:-4] + '.img'
EnvironmentalCorrelation.rasterize(vector_filename,
feature_image_name)

# generate a proximity map from the features
proximity_header_name = output_directory + '/' + mining_name + \
'_' + vector_name + '_proximity.hdr'
proximity_image_name = proximity_header_name[:-4] + '.img'
EnvironmentalCorrelation.proximity(feature_image_name,
proximity_image_name)
proximity_image = spectral.open_image(proximity_header_name)

# intersect features within proximity
for x in range(mining_image.shape[0]):
for y in range(mining_image.shape[1]):
if mining_image[x, y, 0] == 1 \
and proximity_image[x, y, 0] * pixel_size <= proximity:
correlated_image[x, y, 0] = mining_image[x, y, 0]

# save the environmental correlation image with proximity data
# from each type of hydrographic data passed as input
spectral.io.envi.save_classification(correlated_filename,
correlated_image,
class_names=mining_image.
Expand Down
91 changes: 43 additions & 48 deletions pycoal/mineral.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,6 @@ def convert(cls, library_filename=""):
for line_count, _ in enumerate(input_file):
pass

input_file = open(library_filename, 'r')
# Read Name of Spectra on first line of the file
spectra_line = input_file.readline()
spectra_name = spectra_line[23:]
Expand All @@ -842,53 +841,49 @@ def convert(cls, library_filename=""):
# Write new file in the form of an ASTER .spectrum.txt file while
# using stored
# Spectra Name and stored Spectra Wavelength values`
input_file = open(library_filename, 'w')
input_file.write('Name:')
input_file.write(spectra_name)
input_file.write('Type:\n')
input_file.write('Class:\n')
input_file.write('Subclass:\n')
input_file.write('Particle Size: Unknown\n')
input_file.write('Sample No.: 0000000000\n')
input_file.write('Owner:\n')
input_file.write('Wavelength Range: ALL\n')
input_file.write(
'Origin: Spectra obtained from the Noncoventional Exploitation '
'Factors\n')
input_file.write(
'Data System of the National Photographic Interpretation '
'Center.\n')
input_file.write(
'Description: Gray and black construction asphalt. The sample '
'was\n')
input_file.write(
'soiled and weathered, with some limestone and quartz aggregate\n')
input_file.write('showing.\n')
input_file.write('\n')
input_file.write('\n')
input_file.write('\n')
input_file.write('Measurement: Unknown\n')
input_file.write('First Column: X\n')
input_file.write('Second Column: Y\n')
input_file.write('X Units: Wavelength (micrometers)\n')
input_file.write('Y Units: Reflectance (percent)\n')
input_file.write('First X Value:\n')
input_file.write('Last X Value:\n')
input_file.write('Number of X Values:\n')
input_file.write('Additional Information:\n')
input_file.write('\n')
j = 0
spectra_values_file.close()
# Read in values saved in SpectraValues.txt and output them to the
# library_filename
spectra_values_file = open('SpectraValues.txt', 'r')
while (j < line_count):
spectra_wave_length = spectra_values_file.readline()
input_file.write(spectra_wave_length)
j = j + 1
# Close all open files
input_file.close()
spectra_values_file.close()
with open(library_filename, 'w') as input_file:
input_file.write('Name:')
input_file.write(spectra_name)
input_file.write('Type:\n')
input_file.write('Class:\n')
input_file.write('Subclass:\n')
input_file.write('Particle Size: Unknown\n')
input_file.write('Sample No.: 0000000000\n')
input_file.write('Owner:\n')
input_file.write('Wavelength Range: ALL\n')
input_file.write(
'Origin: Spectra obtained from the Noncoventional Exploitation '
'Factors\n')
input_file.write(
'Data System of the National Photographic Interpretation '
'Center.\n')
input_file.write(
'Description: Gray and black construction asphalt. The sample '
'was\n')
input_file.write(
'soiled and weathered, with some limestone and quartz aggregate\n')
input_file.write('showing.\n')
input_file.write('\n')
input_file.write('\n')
input_file.write('\n')
input_file.write('Measurement: Unknown\n')
input_file.write('First Column: X\n')
input_file.write('Second Column: Y\n')
input_file.write('X Units: Wavelength (micrometers)\n')
input_file.write('Y Units: Reflectance (percent)\n')
input_file.write('First X Value:\n')
input_file.write('Last X Value:\n')
input_file.write('Number of X Values:\n')
input_file.write('Additional Information:\n')
input_file.write('\n')
j = 0
# Read in values saved in SpectraValues.txt and output them to the
# library_filename
with open('SpectraValues.txt', 'r') as spectra_values_file:
while (j < line_count):
spectra_wave_length = spectra_values_file.readline()
input_file.write(spectra_wave_length)
j = j + 1
# Rename library_filename to match ASTER .spectrum.txt file format
os.rename(library_filename, library_filename + '.spectrum.txt')
# Remove temporary file for storing wavelength data
Expand Down
Loading

0 comments on commit 34a97fa

Please sign in to comment.