API Reference
Massipipe: A Python package for batch processing hyperspectral images.
MassiPipe is a data processing pipeline for hyperspectral images. It focuses on conversion to radiance, conversion to reflectance, and glint correction of images of shallow water environments.
The package was developed during a project which used a Resonon Pika-L hyperspectral camera, and parts of the package (radiance and irradiance conversion) are specific to this camera. However, other parts are more general and can be used with any hyperspectral image.
Config
Bases: BaseModel
Top-level configuration including standard SeaBee fields
Source code in massipipe/config.py
ImuDataParser
ImuDataParser is a utility class for parsing and processing IMU (Inertial Measurement Unit) data files generated by Resonon Airborne Hyperspectral imagers. It provides methods to read location files (.lcf), image line timestamps (.times) files, and interpolate the IMU data to match the image timestamps.
Source code in massipipe/georeferencing.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
|
read_lcf_file(lcf_file_path, convert_to_unix_time=True, time_rel_to_file_start=False)
staticmethod
Read location files (.lcf) generated by Resonon Airborne Hyperspectral imager
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lcf_file_path
|
Union[str, Path]
|
Path to lcf file. Usually a "sidecar" file to an hyperspectral image with same "base" filename. |
required |
convert_to_unix_time
|
bool
|
Whether to convert timestamps to UNIX time, which is standard for many computer / sensor systems. Timestamps in LCF file are originally in "GPS time" (see https://en.wikipedia.org/wiki/Global_Positioning_System#Timekeeping) |
True
|
time_rel_to_file_start
|
bool
|
Boolean indicating if first timestamp should be subtracted from each timestamp, making time relative to start of file. If True, the value of convert_to_unix_time as no effect. |
False
|
Returns:
Name | Type | Description |
---|---|---|
lcf_data |
Dict[str, NDArray]
|
Dictionary with keys describing the type of data, and data formatted as numpy arrays. All arrays have equal length. The 7 types of data (keys) are: 'time': System time in seconds (GPS time). 'roll': Roll angle in radians, positive for "right wing up". 'pitch': Pitch angle in radians,positive nose up. 'yaw': (heading) in radians, zero at due North, PI/2 at due East. 'longitude': Longitude in decimal degrees, negative for west longitude. 'latitude': Latitude in decimal degrees, negative for southern hemisphere. 'altitude': Altitude in meters relative to the WGS-84 ellipsiod. |
Notes
The LCF file format was shared by Casey Smith at Resonon on February 16. 2021. The LCF specification was inherited from Space Computer Corp.
Source code in massipipe/georeferencing.py
read_times_file(times_file_path, time_rel_to_file_start=True)
staticmethod
Read image line timestamps (.times) file generated by Resonon camera
Parameters:
Name | Type | Description | Default |
---|---|---|---|
times_file_path
|
Union[Path, str]
|
Path to times file. Usually a "sidecar" file to an hyperspectral image with same "base" filename. |
required |
time_rel_to_file_start
|
bool
|
Boolean indicating if times should be offset so that first timestamp is zero. If not, the original timestamp value is returned. |
True
|
Returns:
Name | Type | Description |
---|---|---|
times |
NDArray
|
Numpy array containing timestamps for every line of the corresponding hyperspectral image. The timestamps are in units of seconds, and are relative to when the system started (values are usually within the 0-10000 second range). If time_rel_to_file_start=True, the times are offset so that the first timestamp is zero. The first timestamp of the times file and the first timestamp of the corresponding lcf file (GPS/IMU data) are assumed to the recorded at exactly the same time. If both sets of timestamps are offset so that time is measured relative to the start of the file, the times can be used to calculate interpolated GPS/IMU values for each image line. |
Source code in massipipe/georeferencing.py
interpolate_lcf_to_times(lcf_data, image_times, convert_to_list=True)
staticmethod
Interpolate LCF data to image line times
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lcf_data
|
dict
|
Dictionary with data read from *.lcf file |
required |
image_times
|
NDArray
|
Array of time stamps from *.times file |
required |
convert_to_list
|
bool
|
Whether to convert interpolated LCF data to list (useful for saving data as JSON). If False, interpolated values in lcf_data_interp are formatted as NDArray. |
True
|
Returns:
Name | Type | Description |
---|---|---|
lcf_data_interp |
dict[list | NDArray]
|
Version of lcf_data with all measured values interpolated to image timestamps. |
Source code in massipipe/georeferencing.py
read_and_save_imu_data(lcf_path, times_path, json_path)
Parse .lcf and .times files and save as JSON
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lcf_path
|
Union[Path, str]
|
Path to *.lcf (IMU data) file |
required |
times_path
|
Union[Path, str]
|
Path to *.times (image line timestamps) file |
required |
json_path
|
Union[Path, str]
|
Path to output JSON file |
required |
Source code in massipipe/georeferencing.py
ImuGeoTransformer
Class for calculating affine geotransform based on IMU data and image shape.
Attributes:
Name | Type | Description |
---|---|---|
camera_opening_angle |
float
|
Full opening angle of camera, in radians. |
pitch_offset |
float
|
Forward pointing angle of the camera relative to nadir, in radians. |
roll_offset |
float
|
Right pointing angle of the camera relative to nadir, in radians. |
altitude_offset |
float
|
Offset added to the estimated altitude. |
utm_x_offset |
float
|
Offset in the UTM x-coordinate. |
utm_y_offset |
float
|
Offset in the UTM y-coordinate. |
imu_data |
dict
|
IMU data loaded from JSON file. |
image_shape |
tuple
|
Shape of the hyperspectral image. |
utm_x |
float
|
UTM x-coordinate of the IMU data. |
utm_y |
float
|
UTM y-coordinate of the IMU data. |
camera_origin |
NDArray
|
Origin of the camera in UTM coordinates. |
t_total |
float
|
Total time duration of IMU data. |
dt |
float
|
Sampling interval of IMU data. |
v_alongtrack |
NDArray
|
Along-track velocity vector, in m/s. |
u_alongtrack |
NDArray
|
Unit vector (easting, northing) pointing along flight direction |
gsd_alongtrack |
float
|
Ground sampling distance along track. |
swath_length |
float
|
Length of the swath along track. |
mean_altitude |
float
|
Mean altitude of the UAV during imaging. |
u_acrosstrack |
NDArray
|
Unit vector (easting, northing) pointing left relative to flight direction. The direction is chosen to match that of the image coordinate system: Origin in upper left corner, down (increasing line number) corresponds to positive along-track direction, right (increasing sample number) corresponds to positive cross-track direction. |
swath_width |
float
|
Width of the swath across track. |
gsd_acrosstrack |
float
|
Ground sampling distance across track. |
image_origin |
NDArray
|
Coordinates of the image origin. |
geotransform |
tuple
|
6-element affine transform for the image. |
rotation_deg |
float
|
Image rotation in degrees. |
utm_zone_number |
int
|
UTM zone number. |
utm_zone_hemi |
str
|
UTM hemisphere (North or South). |
envi_map_info |
str
|
ENVI "map info" string, including image rotation. |
Source code in massipipe/georeferencing.py
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 |
|
__init__(imu_data_path, image_header_path, camera_opening_angle=None, pitch_offset=None, roll_offset=None, altitude_offset=None, utm_x_offset=None, utm_y_offset=None, assume_square_pixels=True)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
imu_data_path
|
Union[Path, str]
|
Path to JSON file with IMU data |
required |
image_header_path
|
Union[Path, str]
|
Path to header for hyperspectral image |
required |
camera_opening_angle
|
float
|
Full opening angle of camera, in degrees. Corresponds to angle between rays hitting leftmost and rightmost pixels of image. |
36.5
|
pitch_offset
|
float
|
How much forward the camera is pointing relative to nadir (degrees) |
0.0
|
roll_offset
|
float
|
How much to the right ("right wing up") the camera is pointing relative to nadir (degrees). |
0.0
|
altitude_offset
|
float
|
Offset added to the estimated altitude. If the UAV was higher in reality than that estimated by the GeoTransformer object, add a positive altitude_offset. |
0.0
|
utm_x_offset
|
Optional[float]
|
How far from the real position the IMU data position is, measured in meters. If the IMU data is too far east, utm_x_offset is positive. If the IMU data is too far north, utm_y_offset is positive. The offset is assumed to be constant across a dataset. |
None
|
utm_y_offset
|
Optional[float]
|
How far from the real position the IMU data position is, measured in meters. If the IMU data is too far east, utm_x_offset is positive. If the IMU data is too far north, utm_y_offset is positive. The offset is assumed to be constant across a dataset. |
None
|
assume_square_pixels
|
bool
|
Whether to assume that the original image was acquired with flight parameters (flight speed, frame rate, altitude) that would produce square pixels. If true, the altitude of the camera is estimated from the shape of the image and the (along-track) swath length. This can be useful in cases where absolute altitude measurement of the camera IMU is not very accurate. |
True
|
Source code in massipipe/georeferencing.py
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
|
_calc_time_attributes()
Calculate time duration and sampling interval of IMU data
Returns:
Name | Type | Description |
---|---|---|
t_total |
float
|
Total time duration of IMU data |
dt |
float
|
Sampling interval of IMU data |
Source code in massipipe/georeferencing.py
_calc_alongtrack_properties()
Calculate along-track velocity, gsd, and swath length
Returns:
Name | Type | Description |
---|---|---|
v_alongtrack |
NDArray
|
Along-track velocity vector |
u_alongtrack |
NDArray
|
Along-track unit vector |
gsd_alongtrack |
float
|
Ground sampling distance along track |
swath_length |
float
|
Length of the swath along track |
Source code in massipipe/georeferencing.py
_calc_mean_altitude(assume_square_pixels)
Calculate mean altitude of UAV during imaging
Parameters:
Name | Type | Description | Default |
---|---|---|---|
assume_square_pixels
|
bool
|
If true, the across-track sampling distance is assumed to be equal to the alongtrack sampling distance. The altitude is calculated based on this and the number of cross-track samples. If false, the mean of the altitude values from the imu data is used. In both cases, the altitude offset is added. |
required |
Returns:
Name | Type | Description |
---|---|---|
altitude |
float
|
Mean altitude of the UAV |
Source code in massipipe/georeferencing.py
_calc_acrosstrack_properties()
Calculate cross-track unit vector, swath width and sampling distance
Returns:
Name | Type | Description |
---|---|---|
u_acrosstrack |
NDArray
|
Cross-track unit vector |
swath_width |
float
|
Width of the swath across track |
gsd_acrosstrack |
float
|
Ground sampling distance across track |
Source code in massipipe/georeferencing.py
_calc_image_origin()
Calculate location of image pixel (0,0) in georeferenced coordinates (x,y)
Returns:
Name | Type | Description |
---|---|---|
image_origin |
NDArray
|
Coordinates of the image origin |
Source code in massipipe/georeferencing.py
_calc_image_rotation()
Calculate image rotation in degrees (zero for image origin in NW corner)
Returns:
Name | Type | Description |
---|---|---|
rotation_deg |
float
|
Image rotation in degrees |
Source code in massipipe/georeferencing.py
_get_utm_zone()
Get UTM zone and hemisphere (North or South)
Returns:
Name | Type | Description |
---|---|---|
utm_zone_number |
int
|
UTM zone number |
utm_zone_hemi |
str
|
UTM hemisphere (North or South) |
Source code in massipipe/georeferencing.py
get_image_transform(ordering='alphabetical')
Get 6-element affine transform for image
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ordering
|
(str, {alphabetical, worldfile})
|
If 'alphabetical', return A,B,C,D,E,F If 'worldfile', return A,D,B,E,C,F See https://en.wikipedia.org/wiki/World_file |
"alphabetical"
|
Returns:
Name | Type | Description |
---|---|---|
transform |
tuple[float]
|
6-element affine transform |
Raises:
Type | Description |
---|---|
ValueError
|
If invalid ordering parameter is used |
Source code in massipipe/georeferencing.py
get_envi_map_info()
Create ENVI "map info" string, including image rotation
ENVI header files support a "map info" field which describes the geotransform for the image. The field has up to 11 parameters:
- Projection name
- Reference (tie point) pixel x location (in file coordinates)
- Reference (tie point) pixel y location (in file coordinates)
- Pixel easting
- Pixel northing
- x pixel size (on ground)
- y pixel size (on ground)
- Projection zone (UTM only)
- North or South (UTM only)
- Datum
- Units
NV5 / ENVI does not natively support geotransforms that are rotated. However,
GDAL supports the use of specifying a rotation argument ("rotation=
Returns: map_info: str String with map info formatted in ENVI header style. Example: "{UTM, 1, 1, 581226.666764, 7916192.56364, 5.2, 5.2, 4, North, WGS-84, rotation=42}"
References
https://www.nv5geospatialsoftware.com/docs/ENVIHeaderFiles.html https://github.com/ornldaac/AVIRIS-NG_ENVI-rotatedgrid https://gis.stackexchange.com/questions/229952/rotate-envi-hyperspectral-imagery-with-gdal https://trac.osgeo.org/gdal/ticket/1778#comment:8 https://github.com/OSGeo/gdal/blob/master/frmts/raw/envidataset.cpp#L1393
Source code in massipipe/georeferencing.py
save_image_geotransform(geotransform_json_path)
Save geotransform and related parameters as JSON file
The following parameters are saved to file: utm_epsg: int Integer EPSG code describing UTM zone (CRS) geotransform: tuple 6-element tuple (a,b,c,d,e,f) with affine transform map_info: str "map info" string in ENVI header format gsd_alongtrack: float Ground sampling distance (resolution) along flight track, in meters gsd_acrosstrack: float Ground sampling distance (resolution) across flight track, in meters swath_length: float Length of image swath (along track), in meters swath_width: float Width of image swath (across track), in meters rotation_deg: float Rotation of image in degrees, clockwise, +/- 180 degrees
Parameters:
Name | Type | Description | Default |
---|---|---|---|
geotransform_json_path
|
Union[Path, str]
|
Path to JSON file |
required |
Source code in massipipe/georeferencing.py
FlatSpecGlintCorrector
Perform glint correction on reflectance images using a flat glint spectrum assumption.
This class removes glint by subtracting the mean near-infrared (NIR) value from each spectrum, based on the assumption that the glint is spectrally flat. Optionally, it applies smoothing with a Savitsky-Golay filter to the corrected image.
Source code in massipipe/glint.py
__init__(smooth_with_savitsky_golay=True)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
smooth_with_savitsky_golay
|
bool
|
Whether to smooth glint corrected images using a Savitsky-Golay filter. |
True
|
Source code in massipipe/glint.py
glint_correct_image(refl_image, refl_wl)
Remove sun and sky glint from an image by assuming a flat glint spectrum.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
refl_image
|
NDArray
|
Reflectance image with shape (n_lines, n_samples, n_bands). |
required |
refl_wl
|
NDArray
|
Wavelength vector (nm) for each band in refl_image. |
required |
Returns:
Type | Description |
---|---|
NDArray
|
Glint corrected reflectance image with the same shape as refl_image. The mean NIR value is subtracted from each spectrum so that only the spectral offset is changed while preserving the overall spectral shape. |
Notes
- Assumes negligible water-leaving radiance in the NIR region.
- Assumes that the sun and sky glint have a flat spectrum, which can be a close approximation.
Source code in massipipe/glint.py
glint_correct_image_file(image_path, glint_corr_image_path, **kwargs)
Read an ENVI header file, perform glint correction, and save the corrected image.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
image_path
|
Union[Path, str]
|
Path to the hyperspectral image header. |
required |
glint_corr_image_path
|
Union[Path, str]
|
Path to save the glint corrected image header. |
required |
Source code in massipipe/glint.py
HedleyGlintCorrector
Perform glint correction using a fitted linear regression model (Hedley method).
This class corrects glint by fitting a linear model to reference spectra and then applying this model to correct the visible spectrum of the input image. It supports optional smoothing, dark spectrum subtraction, and adjusts for negative values to ensure valid outputs.
Source code in massipipe/glint.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
|
__init__(smooth_spectra=True, subtract_dark_spec=True, set_negative_values_to_zero=False, max_invalid_frac=0.05)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
smooth_spectra
|
bool
|
Whether to smooth glint corrected images using a Savitzky-Golay filter. |
True
|
subtract_dark_spec
|
bool
|
Whether to subtract estimated minimum value in training data (for each wavelength) from glint corrected image. This has the effect of removing "background" spectrum caused by e.g. reflection of the sky and water column scattering. |
True
|
set_negative_values_to_zero
|
bool
|
Glint is corrected by subtracting estimated glint from the original image. The subtraction process may result in some spectral bands getting negative values. If the fraction of pixels that is negative is larger than max_invalid_fraction, all pixel values are set to zero, indicating an invalid pixel. |
False
|
max_invalid_frac
|
float
|
The fraction of spectral bands that is allowed to be invalid (i.e. zero) before the whole pixel is declared invalid and all bands are set to zero. Allowing some invalid bands may keep useful information, but a high number of invalid bands results in severe spectral distortion and indicates poor data quality. |
0.05
|
Source code in massipipe/glint.py
fit_to_reference_images(reference_image_paths, reference_image_ranges=None, sample_frac=0.5)
Fit the glint correction model based on spectra from reference hyperspectral images.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
reference_image_paths
|
list[Union[Path, str]]
|
List of paths to reference hyperspectral image headers. |
required |
reference_image_ranges
|
Union[None, list[Union[None, list[int]]]]
|
List of pixel ranges to use as reference from each image. If None, the full image is used. Ranges are specified as [line_start, line_end, sample_start, sample_end]. |
None
|
sample_frac
|
float
|
Fraction of total pixels used for training (0.0 to 1.0). Pixels are randomly sampled. |
0.5
|
Source code in massipipe/glint.py
fit(train_spec, wl)
Fit the linear glint correction model to training spectra.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
train_spec
|
NDArray
|
Training spectra with shape (n_samples, n_bands). |
required |
wl
|
NDArray
|
Wavelength vector (nm). |
required |
Source code in massipipe/glint.py
linear_regression_multiple_dependent_variables(x, Y)
staticmethod
Compute slopes for a multiple-output linear regression using a single predictor.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
x
|
NDArray
|
Predictor variable, shape (n_samples, 1). |
required |
Y
|
NDArray
|
Response variables, shape (n_samples, n_variables). |
required |
Returns:
Type | Description |
---|---|
NDArray
|
Regression slopes for each dependent variable as defined in f(x) = a + b*x. |
Notes
- Implementation inspired by https://stackoverflow.com/questions/ 48105922/numpy-covariance-between-each-column-of-a-matrix-and-a-vector
Source code in massipipe/glint.py
glint_correct_image(image)
Remove sun and sky glint from a hyperspectral image using the fitted linear model.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
image
|
NDArray
|
Hyperspectral image with shape (n_lines, n_samples, n_bands). |
required |
Returns:
Type | Description |
---|---|
NDArray
|
Glint corrected image containing only visible light spectra. |
Notes
- Based on the assumption of negligible water-leaving radiance in the NIR, it subtracts a modeled glint estimate from the visible bands.
Source code in massipipe/glint.py
glint_correct_image_file(image_path, glint_corr_image_path, **kwargs)
Read a hyperspectral image from an ENVI header, apply glint correction, and save the result.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
image_path
|
Union[Path, str]
|
Path to the input ENVI header file. |
required |
glint_corr_image_path
|
Union[Path, str]
|
Path to save the glint corrected ENVI header file. |
required |
Source code in massipipe/glint.py
IrradianceConverter
A class to convert raw spectra to irradiance using calibration data.
Methods:
Name | Description |
---|---|
convert_raw_spectrum_to_irradiance |
set_irradiance_outside_wl_limits_to_zero=True, keep_original_dimensions=True) Convert raw spectrum to irradiance. |
convert_raw_file_to_irradiance |
Read raw spectrum, convert to irradiance, and save. |
Source code in massipipe/irradiance.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
|
__init__(irrad_cal_file, irrad_cal_dir_name='downwelling_calibration_spectra', wl_min=None, wl_max=None)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
irrad_cal_file
|
Union[Path, str]
|
Path to downwelling irradiance calibration file. |
required |
irrad_cal_dir_name
|
str
|
Name of folder which calibration files will be unzipped into. |
"downwelling_calibration_spectra"
|
wl_min
|
Union[float, None]
|
Shortest valid wavelength (nm) in irradiance spectrum. |
None
|
wl_max
|
Union[float, None]
|
Longest valid wavelength (nm) in irradiance spectrum. |
None
|
Source code in massipipe/irradiance.py
_unzip_irrad_cal_file(unzip_into_nonempty_dir=False)
Unzip *.dcp file (which is a zip file).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
unzip_into_nonempty_dir
|
bool
|
Whether to unzip into a non-empty directory. |
False
|
Source code in massipipe/irradiance.py
_load_cal_dark_and_sensitivity_spectra()
Load dark current and irradiance sensitivity spectra from cal. files.
Source code in massipipe/irradiance.py
convert_raw_spectrum_to_irradiance(raw_spec, raw_metadata, set_irradiance_outside_wl_limits_to_zero=True, keep_original_dimensions=True)
Convert raw spectrum to irradiance.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
raw_spec
|
NDArray
|
Raw spectrum. |
required |
raw_metadata
|
dict
|
Dictionary with ENVI metadata for raw spectrum. |
required |
set_irradiance_outside_wl_limits_to_zero
|
bool
|
Whether to set spectrum values outside wavelength limits to zero. If False, values outside valid range are treated the same as values inside valid range. |
True
|
keep_original_dimensions
|
bool
|
Whether to format output spectrum with same (singleton) dimensions as input spectrum. Can be useful for broadcasting. |
True
|
Returns:
Type | Description |
---|---|
NDArray
|
Spectrum converted to spectral irradiance, unit W/(m2*nm). |
Notes
The irradiance conversion spectrum is inversely scaled with the input spectrum shutter. E.g., if the input spectrum has a higher shutter value than the calibration file (i.e. higher values per amount of photons), the conversion spectrum values are decreased to account for this. Dark current is assumed to be independent of shutter value.
Source code in massipipe/irradiance.py
convert_raw_file_to_irradiance(raw_spec_path, irrad_spec_path)
Read raw spectrum, convert to irradiance, and save.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
raw_spec_path
|
Union[Path, str]
|
Path to ENVI header file for raw spectrum. |
required |
irrad_spec_path
|
Union[Path, str]
|
Path to ENVI header file for saving irradiance spectrum. |
required |
Source code in massipipe/irradiance.py
Pipeline
Pipeline class for processing hyperspectral datasets.
This class encapsulates all processing steps required to convert raw or radiance data into calibrated and georeferenced image products. It manages configuration loading, logging setup, file path generation, conversion procedures, glint correction, mosaicing and export operations.
Source code in massipipe/pipeline.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 |
|
__init__(dataset_dir, config_file_name='config.seabee.yaml')
Parameters:
Name | Type | Description | Default |
---|---|---|---|
dataset_dir
|
Union[Path, str]
|
Path to the dataset directory containing required subfolders. The required subfolders are either "0_raw" and "calibration" (for processing from raw data), or "1a_radiance" and "imudata" (for processing from radiance data). |
required |
config_file_name
|
str
|
Name of the YAML configuration file. A template is generated if the file does not exist. |
'config.seabee.yaml'
|
Raises:
Type | Description |
---|---|
FileNotFoundError
|
If required folders (e.g. "0_raw" or "calibration") are missing. |
Source code in massipipe/pipeline.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
|
load_config_from_file()
Load or reload configuration from a YAML file.
Reads the configuration from self.config_file_path
, validates it using Pydantic,
and assigns the loaded options to self.config
. Logs warnings on validation errors.
Source code in massipipe/pipeline.py
_configure_file_logging()
Configure file logging for pipeline execution.
Creates a logs directory if needed and initializes a file handler with a timestamped log file.
Source code in massipipe/pipeline.py
_check_data_starting_point()
Determine if processing should start from raw or radiance data.
Returns:
Type | Description |
---|---|
str
|
"raw" if raw data exists and "radiance" if radiance data exists. |
Raises:
Type | Description |
---|---|
FileNotFoundError
|
If neither raw nor radiance data is found in the dataset directory. |
Source code in massipipe/pipeline.py
_validate_raw_files()
Check that all expected raw files exist
Returns:
times_paths, lcf_paths: list[Path] Lists of paths to .times and .lcf files for every valid raw file
Source code in massipipe/pipeline.py
_get_image_number(raw_image_path)
staticmethod
Get image number from raw image
Parameters:
Name | Type | Description | Default |
---|---|---|---|
raw_image_path
|
Union[Path, str]
|
Path to raw image (ENVI header file) |
required |
Returns:
Type | Description |
---|---|
int
|
Image number |
Examples:
Notes
Raw files are numbered sequentially, but the numbers are not zero-padded. This can lead to incorrect sorting of the images, e.g. ['im_1','im_2','im_10'] (simplified names for example) are sorted ['im_1','im_10','im_2']. By extracting the numbers from filenames of raw files and sorting explicitly on these (as integers), correct ordering can be achieved.
Source code in massipipe/pipeline.py
_create_base_file_names()
Create numbered base names for processed files
Source code in massipipe/pipeline.py
_create_processed_file_paths()
Define default subfolders for processed files
Source code in massipipe/pipeline.py
_get_raw_spectrum_paths()
Search for raw files matching Resonon default naming
Source code in massipipe/pipeline.py
_get_radiance_calibration_path()
Search for radiance calibration file (*.icp)
Source code in massipipe/pipeline.py
_get_irradiance_calibration_path()
Search for irradiance calibration file (*.dcp)
Source code in massipipe/pipeline.py
create_quicklook_images()
Create quicklook versions of hyperspectral images
Source code in massipipe/pipeline.py
parse_and_save_imu_data()
Parse .lcf and .times files with IMU data and save as JSON
Source code in massipipe/pipeline.py
convert_raw_images_to_radiance()
Convert raw hyperspectral images (DN) to radiance (microflicks)
Source code in massipipe/pipeline.py
_create_rgb_geotiff(hyspec_paths, geotransform_paths, geotiff_paths, geotiff_overwrite, rgb_wl)
staticmethod
Create georeferenced RGB GeoTIFF versions of hyperspectral image
Parameters:
Name | Type | Description | Default |
---|---|---|---|
hyspec_paths
|
list[Path]
|
Paths to hyperspectral files from which to create RGB images. If the file does not exist, the corresponding image is skipped. |
required |
geotransform_paths
|
list[Path]
|
Paths to geotransform files with affine transform for images. If the file does not exist, the corresponding image is skipped. |
required |
geotiff_paths
|
list[Path]
|
Paths for output ((GeoTIFF) files |
required |
geotiff_overwrite
|
bool
|
Boolean indicating if existing GeoTIFF files should be overwritten. |
required |
rgb_wl
|
tuple[float, float, float]
|
Wavelengths (in nm) to use for red, green and blue. |
required |
Source code in massipipe/pipeline.py
create_radiance_rgb_geotiff()
Create georeferenced RGB GeoTIFF versions of radiance
Source code in massipipe/pipeline.py
convert_raw_spectra_to_irradiance()
Convert raw spectra (DN) to irradiance (W/(m2*nm))
Source code in massipipe/pipeline.py
calibrate_irradiance_wavelengths()
Calibrate irradiance wavelengths using Fraunhofer absorption lines
Source code in massipipe/pipeline.py
glint_correct_radiance_images()
Remove water surface reflections of sun and sky light
Source code in massipipe/pipeline.py
create_glint_corrected_radiance_rgb_geotiff()
Create georeferenced GeoTIFF versions of glint corrected radiance
Source code in massipipe/pipeline.py
convert_radiance_images_to_reflectance()
Convert radiance images (microflicks) to reflectance (unitless)
Source code in massipipe/pipeline.py
add_irradiance_to_radiance_header()
Pre-process irradiance for reflectance calc. and save to radiance header
Source code in massipipe/pipeline.py
add_mapinfo_to_radiance_header()
Add ENVI mapinfo (geotransform) to radiance header
Source code in massipipe/pipeline.py
glint_correct_reflectance_images()
Correct for sun and sky glint in reflectance images
Source code in massipipe/pipeline.py
create_glint_corrected_reflectance_rgb_geotiff()
Create georeferenced GeoTIFF versions of glint corrected reflectance
Source code in massipipe/pipeline.py
_mosaic_geotiffs(geotiff_paths, mosaic_path, mosaic_overwrite, overview_factors, convert_to_8bit=True)
staticmethod
Mosaic GeoTIFF images into single GeoTIFF with overviews
Parameters:
Name | Type | Description | Default |
---|---|---|---|
geotiff_paths
|
list[Path]
|
List of GeoTIFFs to mosaic |
required |
mosaic_path
|
Path
|
Path to output GeoTIFF |
required |
mosaic_overwrite
|
bool
|
Whether to overwrite existing output GeoTIFF. |
required |
overview_factors
|
Sequence[int]
|
GeoTIFF overview factors, typically powers of 2 Used to add "pyramid" of lower-resolution images for faster image browsing. |
required |
convert_to_8bit
|
bool
|
If true, the mosaic is percentile stretched and converted to 8-bit. This decreases file size and enhances contrast, at the cost of losing the (physical) units of the original image. |
True
|
Source code in massipipe/pipeline.py
mosaic_radiance_geotiffs()
Merge radiance RGB images into mosaic with overviews
Source code in massipipe/pipeline.py
mosaic_radiance_gc_geotiffs()
Merge radiance_gc RGB images into mosaic with overviews
Source code in massipipe/pipeline.py
mosaic_reflectance_gc_geotiffs()
Merge reflectance_gc RGB images into mosaic with overviews
Source code in massipipe/pipeline.py
delete_existing_products(delete_quicklook=True, delete_radiance=True, delete_radiance_gc=True, delete_reflectance=True, delete_reflectance_gc=True, delete_geotransform=True, delete_imudata=True, delete_mosaics=True)
Delete existing image products ("reset" after previous processing)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
delete_quicklook
|
bool
|
If true, delete 0b_quicklook folder (if it exists) |
True
|
delete_radiance
|
bool
|
If true, delete 1a_radiance folder (if it exists) If data "starting point" is radiance and not raw files, radiance will not be deleted (delete manually if needed). |
True
|
delete_radiance_gc
|
bool
|
If true, delete 1b_radiance folder (if it exists) |
True
|
delete_reflectance
|
bool
|
If true, delete 2a_reflectance folder (if it exists) |
True
|
delete_reflectance_gc
|
bool
|
If true, delete 2b_reflectance folder (if it exists) |
True
|
delete_geotransform
|
bool
|
If true, delete geotransform folder (if it exists) |
True
|
delete_imudata
|
bool
|
If true, delete imudata folder (if it exists) If data "starting point" is radiance and not raw files, imu data will not be deleted (delete manually if needed). |
True
|
delete_mosaics
|
bool
|
If true, delete mosaics folder (if it exists) |
True
|
Source code in massipipe/pipeline.py
run_quicklook()
Create quicklook versions of images (percentile stretched)
Source code in massipipe/pipeline.py
run_raw_data_processing()
Run all data processing steps based on raw data
Source code in massipipe/pipeline.py
run_glint_correction()
Run glint correction using parameters defined in YAML file
The processing steps include: - Fitting a glint correction model to radiance images - Running glint correction and saving glint corrected images - Creating RGB GeoTiff versions of glint corrected images
See massipipe.config.Config and template YAML file for all options.
Source code in massipipe/pipeline.py
run_mosaics()
Run all mosaicing operations
Source code in massipipe/pipeline.py
run()
Run all processing steps
export()
Export dataset to ZIP file for archival / publishing
Source code in massipipe/pipeline.py
QuickLookProcessor
Source code in massipipe/quicklook.py
__init__(rgb_wl=None, percentiles=None)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
rgb_wl
|
Optional[Tuple[float, float, float]]
|
Wavelengths (in nm) for generating RGB images. If None, uses default (640.0, 550.0, 460.0). |
None
|
percentiles
|
Optional[Tuple[float, float]]
|
Percentile limits for percentile stretching of images. If None, uses default (2, 98). |
None
|
Source code in massipipe/quicklook.py
create_quicklook_image_file(raw_path, quicklook_path)
Create per-band percentile stretched RGB image file from raw hyperspectral image.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
raw_path
|
Union[Path, str]
|
Path to raw hyperspectral image (header file). |
required |
quicklook_path
|
Union[Path, str]
|
Path to output PNG image file. |
required |
Source code in massipipe/quicklook.py
RadianceConverter
A class for converting raw hyperspectral images from Pika L cameras to radiance.
Attributes:
Name | Type | Description |
---|---|---|
radiance_calibration_file |
Union[Path, str]
|
Path to Imager Calibration Pack (*.icp) file. |
rc_dataset |
RadianceCalibrationDataset
|
A radiance calibration dataset object representing the calibration data supplied in the *.icp file. |
rad_conv_frame |
NDArray
|
Frame representing conversion factors from raw data to radiance for every pixel and wavelength. |
rad_conv_metadata |
dict
|
ENVI metadata for rad_conv_frame. |
Methods:
Name | Description |
---|---|
convert_raw_image_to_radiance |
Convert single image (3D array) from raw to radiance. |
convert_raw_file_to_radiance |
Read raw file, convert, and save as radiance image. |
Notes
Most image sensors register some amount of "dark current", i.e. a signal which is present even though no photons enter the sensor. The dark current should be subtracted for the measurement to be as accurate as possible. The amount of dark current also depends on camera gain (signal amplification) and camera shutter (time available for the sensor to collect photons). The *.icp calibration file (ICP = "Imager Calibration Pack") is a ZIP archive which includes dark current measurements taken at different gain and shutter settings (raw images). To remove dark current from a new image, this set of dark current frames is searched, and the one which best matches the gain and shutter values of the new image is used as a reference. The dark frame needs to be scaled to account for differences in binning, gain and shutter between it and the new image. The dark frame is then subtracted from the image.
To convert raw images from digital numbers to radiance, a physical quantity, the raw images are multiplied with a "radiance conversion frame". This frame represents "microflicks per digital number" for every pixel and every spectral channel, where the spectral radiance unit "flick" is defined as "watts per steradian per square centimeter of surface per micrometer of span in wavelength" (see https://en.wikipedia.org/wiki/Flick_(physics) ). The radiance conversion frame also needs to be scaled to account for differences in binning, gain and shutter.
When both the dark current frame (DCF) and the radiance conversion frame (RCF) have been scaled to match the raw input image (IM), the radiance output image (OI) is given by OI = (IM-DCF)*RCF
Note that the conversion assumes that the camera response is completely linear after dark current is removed. This may not be completely accurate, but is assumed to be within an acceptable margin of error.
Source code in massipipe/radiance.py
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
|
__init__(radiance_calibration_file, set_saturated_pixels_to_zero=True, saturation_value=2 ** 12 - 1)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
radiance_calibration_file
|
Union[Path, str]
|
Path to Imager Calibration Pack (.icp) file. The .icp file is a zip archive, and the file will be unzipped into a subfolder in the same folder containing the *.icp file. |
required |
set_saturated_pixels_to_zero
|
Union[bool, None]
|
If True, saturated pixels are set to all-zero (across all bands). |
True
|
saturation_value
|
int
|
Maximum digital number for camera sensor. |
2 ** 12 - 1
|
Source code in massipipe/radiance.py
_get_rad_conv_frame()
Read radiance conversion frame from file and save as attribute.
Source code in massipipe/radiance.py
_get_best_matching_dark_frame(raw_image_metadata)
Get dark frame from calibration data that best matches input data.
Source code in massipipe/radiance.py
_scale_dark_frame(dark_frame, dark_frame_metadata, raw_image_metadata)
Scale dark frame to match binning for input image.
Source code in massipipe/radiance.py
_scale_rad_conv_frame(raw_image_metadata)
Scale radiance conversion frame to match input binning, gain and shutter.
Source code in massipipe/radiance.py
convert_raw_image_to_radiance(raw_image, raw_image_metadata)
Convert raw image (3D array) to radiance image.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
raw_image
|
NDArray
|
Raw hyperspectral image, shape (n_lines, n_samples, n_channels). The image is assumed to have been created by a Resonon Pika L camera, which has 900 spatial pixels x 600 spectral channels before any binning has been applied. Typically, spectral binning with a bin size of 2 is applied during image acquisition, resulting in images with shape (n_lines, 900, 300). It is assumed that no spectral or spatial (sample) cropping has been applied. Where binning has been applied, it is assumed that - n_samplessample_bin_size = 900 - n_channelschannel_bin_size = 600. |
required |
raw_image_metadata
|
dict
|
ENVI metadata formatted as dict. See spectral.io.envi.open(). |
required |
Returns:
Type | Description |
---|---|
NDArray
|
Radiance image with same shape as raw image, with spectral radiance in units of microflicks = 10e-5 W/(m2*nm). Microflicks are used to be consistent with Resonon formatting, and because microflick values typically are in a range suitable for (memory-efficient) encoding as 16-bit unsigned integer. |
Raises:
Type | Description |
---|---|
ValueError:
|
In case the raw image does not have the expected dimensions. |
References
Source code in massipipe/radiance.py
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 |
|
convert_raw_file_to_radiance(raw_header_path, radiance_header_path, interleave='bip')
Read raw image file, convert to radiance, and save to file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
raw_header_path
|
Union[Path, str]
|
Path to raw hyperspectral image acquired with Resonon Pika L camera. |
required |
radiance_header_path
|
Union[Path, str]
|
Path to save converted radiance image to. The name of the header file should match the 'interleave' argument (default: bip), e.g. 'radiance_image.bip.hdr'. |
required |
interleave
|
str
|
String indicating how binary image file is organized. See spectral.io.envi.save_image(). |
'bip'
|
Notes
The radiance image is saved with the same metadata as the raw image.
Source code in massipipe/radiance.py
ReflectanceConverter
ReflectanceConverter class for converting images from Resonon Pika L cameras to reflectance.
This class provides methods for converting radiance images to reflectance using per-image or mean irradiance spectra. It supports optional Gaussian smoothing of the irradiance spectrum and additional spectral smoothing using a Savitzky-Golay filter.
Attributes:
Name | Type | Description |
---|---|---|
wl_min |
float
|
Lower wavelength bound (nm) for the reflectance image. |
wl_max |
float
|
Upper wavelength bound (nm) for the reflectance image. |
conv_irrad_with_gauss |
bool
|
Indicates if the irradiance spectrum should be smoothed with a Gaussian kernel. |
fwhm_irrad_smooth |
float
|
Full-width-half-maximum for the Gaussian smoothing kernel (in nm). |
smooth_spectra |
bool
|
If True, applies a Savitzky-Golay filter to the reflectance spectra. |
refl_from_mean_irrad |
bool
|
If True, uses a computed mean irradiance value for conversion instead of per-image irradiance. |
ref_irrad_spec_mean |
NDArray
|
Mean irradiance spectrum used for reflectance conversion when refl_from_mean_irrad is True. |
ref_irrad_spec_wl |
NDArray
|
Wavelength array corresponding to the irradiance spectrum. |
Source code in massipipe/reflectance.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
|
__init__(wl_min=None, wl_max=None, conv_irrad_with_gauss=True, fwhm_irrad_smooth=3.5, smooth_spectra=False, refl_from_mean_irrad=False, irrad_spec_paths=None)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
wl_min
|
Optional[float]
|
Minimum wavelength (nm) to include in reflectance image. If None, -float("inf") is used, and no lower limit is applied. |
None
|
wl_max
|
Optional[float]
|
Maximum wavelength (nm) to include in reflectance image. If None, float("inf") is used, and no upper limit is applied. |
None
|
conv_irrad_with_gauss
|
Optional[bool]
|
Indicate if irradiance spectrum should be smoothed with Gaussian kernel. This may be useful if irradiance is measured with a higher spectral resolution than radiance, and thus has sharper "spikes". |
True
|
fwhm_irrad_smooth
|
Optional[float]
|
Full-width-half-maximum for Gaussian smoothing kernel, in nanometers. Only used if conv_irrad_with_gauss==True |
3.5
|
smooth_spectra
|
Optional[bool]
|
Whether to smooth the reflectance spectra using a Savitzky-Golay filter |
False
|
refl_from_mean_irrad
|
bool
|
If True, the mean irradiance for the whole dataset is used for calculating reflectance, rather than the irradiance for a single image. This can be useful if individual irradiance are compromised and using the mean is more "robust". Paths to the irradiance files (irrad_spec_paths) must be specified. |
False
|
irrad_spec_paths
|
Optional[Iterable[Union[Path, str]]]
|
List of paths to irradiance spectra for the dataset. If specified (not None), a mean irradiance value is caluculated based on the spectra, and this irradiance value is used for every reflectance conversion, rather than the |
None
|
Notes
The signal-to-noise ratio of both radiance images and irradiance spectra is generally lower at the low and high ends. When radiance is divided by noisy irradiance values close to zero, the noise can "blow up". Limiting the wavelength range can ensure that the reflectance images have more well-behaved values.
Source code in massipipe/reflectance.py
_get_mean_irrad_spec(irrad_spec_paths)
staticmethod
Read irradiance spectra from file and calculate mean
Source code in massipipe/reflectance.py
conv_spec_with_gaussian(spec, wl)
Convolve spectrum with Gaussian kernel to smooth / blur spectral details
Parameters:
Name | Type | Description | Default |
---|---|---|---|
spec
|
NDArray
|
Input spectrum, shape (n_bands,) |
required |
wl
|
NDArray
|
Wavelengths corresponding to each spectrum value, shape (n_bands,) |
required |
Returns:
Name | Type | Description |
---|---|---|
spec_filtered |
NDArray
|
Filtered / smoothed version of spec, with same dimensions |
Notes
When the kernel extends outside the data while filtering, edges are handled by repeating the nearest sampled value (edge value).
Source code in massipipe/reflectance.py
_interpolate_irrad_to_image_wl(irrad_spec, irrad_wl, image_wl)
staticmethod
Interpolate downwelling spectrum to image wavelengths
Source code in massipipe/reflectance.py
convert_radiance_image_to_reflectance(rad_image, rad_wl, irrad_spec, irrad_wl)
Convert radiance image to reflectance using downwelling spectrum
Parameters:
Name | Type | Description | Default |
---|---|---|---|
rad_image
|
NDArray
|
Spectral radiance image in units of microflicks = 10e-5 W/(srm2nm) Shape (n_lines, n_samples, n_bands) |
required |
rad_wl
|
NDArray
|
Wavelengths (in nanometers) corresponding to each band in rad_image |
required |
irrad_spec
|
NDArray
|
Spectral irradiance in units of W/(m2*nm) |
required |
irrad_wl
|
NDArray
|
Wavelengths (in nanometers) corresponding to each band in irrad_spec |
required |
Returns:
Name | Type | Description |
---|---|---|
refl_image |
NDArray
|
Reflectance image, unitless. Shape is same as rad_image for the first 2 axes, but may be less than that of rad_image along 3rd axis due to limiting of wavelength range. |
refl_wl |
NDArray
|
Wavelengths for reflectance image |
irrad_spec |
NDArray
|
Irradiance spectrum used for reflectance conversion. The spectrum has been interpolated to match the wavelengths of refl_image. |
Source code in massipipe/reflectance.py
convert_radiance_file_to_reflectance(radiance_image_header, irradiance_header, reflectance_image_header)
Read radiance image from file, convert to reflectance and save
Parameters:
Name | Type | Description | Default |
---|---|---|---|
radiance_image_header
|
Union[Path, str]
|
Path to header file for radiance image. |
required |
irradiance_header
|
Union[Path, str]
|
Path to ENVI file containing irradiance measurement corresponding to radiance image file. Not used if self.refl_from_mean_irrad is True - in this case, it can be set to None. |
required |
reflectance_image_header
|
Union[Path, str]
|
Path to header file for (output) reflectance image. Binary file will be saved with same name, except .hdr extension. |
required |
Source code in massipipe/reflectance.py
add_irradiance_spectrum_to_header(radiance_image_header, irradiance_header)
Add irradiance spectrum to radiance image header
Parameters:
Name | Type | Description | Default |
---|---|---|---|
radiance_image_header
|
Union[Path, str]
|
Path to radiance image |
required |
irradiance_header
|
Union[Path, str, None]
|
Path to irradiance spectrum header. If refl_from_mean_irrad == True for ReflectanceConverter, the calculated mean spectrum is used, and irradiance_header can be set to None. |
required |
Source code in massipipe/reflectance.py
convert_radiance_file_with_irradiance_to_reflectance(radiance_image_header, reflectance_image_header)
Convert radiance image with irradiance spectrum in header to reflectance
The irradiance information is read from the field "solar irradiance" in the header of the radiance image file. The irradiance is assumed to be in units W/(m2*um), which is standard for ENVI files, and the irradiance values are assumed to match the wavelengths of the image.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
radiance_image_header
|
Union[Path, str]
|
Path to header file for radiance image. |
required |
reflectance_image_header
|
Union[Path, str]
|
Path to header file for (output) reflectance image. Binary file will be saved with same name, except .hdr extension. |
required |
Source code in massipipe/reflectance.py
read_config(yaml_path)
Parse YAML config file, accepting only basic YAML tags
export_dataset_zip(dataset_dir, quicklook_dir, radiance_dir, imudata_dir, mosaic_visualization_dir, config_file_path)
Export selected parts of dataset to a zip file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
dataset_dir
|
Path
|
The directory containing the dataset to be exported. |
required |
quicklook_dir
|
Path
|
The directory containing quicklook images. |
required |
radiance_dir
|
Path
|
The directory containing radiance data. |
required |
imudata_dir
|
Path
|
The directory containing IMU data. |
required |
mosaic_visualization_dir
|
Path
|
The directory containing mosaic visualizations. |
required |
config_file_path
|
Path
|
The path to the configuration file. |
required |
Returns:
Type | Description |
---|---|
Path
|
The path to the created zip file. |
Notes
This function creates a zip archive containing the specified parts of the dataset, including quicklook images, radiance data, IMU data, mosaic visualizations, and configuration file. It also includes a README and LICENSE file generated for the dataset.
Source code in massipipe/export.py
georeferenced_hyspec_to_rgb_geotiff(hyspec_path, geotiff_path, rgb_wl=None, nodata_value=0.0)
Extract RGB bands from georeferenced hyperspectral image and save as GeoTIFF
Parameters:
Name | Type | Description | Default |
---|---|---|---|
hyspec_path
|
Union[Path, str]
|
Path to hyperspectral image header. Assumes that path to binary image is the same, but without .hdr suffix |
required |
geotiff_path
|
Union[Path, str]
|
Path to (output) GeoTIFF |
required |
rgb_wl
|
tuple[float, float, float]
|
Target wavelengths for RGB bands (closest available bands will be used) |
None
|
Notes
A nodata value of zero is assumed for the hyperspectral image.
Source code in massipipe/georeferencing.py
add_geotiff_overviews(image_path, overview_factors=(2, 4, 8, 16, 32))
Add lower-resolution overviews to a GeoTIFF image file using Rasterio.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
image_path
|
Path
|
Path to the GeoTIFF image to which overviews will be added in-place. |
required |
overview_factors
|
Sequence[int]
|
Downsampling factors for the overviews (default: (2, 4, 8, 16, 32)). Typically factors of 2 are used (2, 4, 8, etc.). |
(2, 4, 8, 16, 32)
|
Raises:
Type | Description |
---|---|
Exception
|
If an error occurs while building the overviews. |
Source code in massipipe/mosaic.py
convert_geotiff_to_8bit(input_image_path, output_image_path, lower_percentile=2, upper_percentile=98, require_positive=True)
Convert a GeoTIFF image to an 8-bit representation using percentile stretching.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
input_image_path
|
Path
|
Path to the original GeoTIFF image. |
required |
output_image_path
|
Path
|
Path to save the 8-bit output GeoTIFF image. |
required |
lower_percentile
|
float
|
Lower percentile (default 2) to set the minimum scaling value. |
2
|
upper_percentile
|
float
|
Upper percentile (default 98) to set the maximum scaling value. |
98
|
require_positive
|
bool
|
If True, enforces a lower bound of zero on the scaling; defaults to True. |
True
|
Raises:
Type | Description |
---|---|
Exception
|
If an error occurs during the conversion process. |
Source code in massipipe/mosaic.py
mosaic_geotiffs(image_paths, mosaic_path)
Merge non-rotated GeoTIFFs into a single mosaic file, and generate overviews using Rasterio.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
image_paths
|
Iterable[Path]
|
Iterable of paths to input GeoTIFF images. Images with rotated geotransforms are not supported. |
required |
mosaic_path
|
Path
|
Path to the output mosaic GeoTIFF file. |
required |
Raises:
Type | Description |
---|---|
Exception
|
If an error occurs during the merging process. |
Source code in massipipe/mosaic.py
find_datasets(base_dir, subdir_search_strings=['0_raw', '1a_radiance'])
Find dataset paths based on expected subdirectories in dataset
Parameters:
Name | Type | Description | Default |
---|---|---|---|
base_dir
|
Path
|
Filesystem starting point (searching tree below this point) |
required |
subdir_search_strings
|
list[str]
|
List with names of subdirectories that are expected to be within a dataset directory. If any of the names match, the dataset directory is included. |
["0_raw", "1a_radiance"]
|
Returns:
Type | Description |
---|---|
dataset_dirs
|
List of dataset dirctories mathcing search criteria. |
Source code in massipipe/pipeline.py
closest_wl_index(wl_array, target_wl)
Get index in sampled wavelength array closest to target wavelength.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
wl_array
|
ArrayLike
|
Array of wavelengths. |
required |
target_wl
|
Union[float, int]
|
Single target wavelength. |
required |
Returns:
Type | Description |
---|---|
int
|
Index of element in wl_array which is closest to target_wl. |
Examples:
Source code in massipipe/utils.py
percentile_stretch_image(image, percentiles=(2, 98), saturation_value=2 ** 12 - 1)
Scale array values within percentile limits to range 0-255.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
image
|
NDArray
|
Image, shape (n_lines, n_samples, n_bands). |
required |
percentiles
|
tuple of float
|
Lower and upper percentiles for stretching. |
(2, 98)
|
saturation_value
|
int
|
Saturation value for the image. |
2 ** 12 - 1
|
Returns:
Name | Type | Description |
---|---|---|
image_stretched |
NDArray, dtype=uint8
|
Image with same shape as input. Image intensity values are stretched so that the lower percentile corresponds to 0 and the higher percentile corresponds to 255 (maximum value for unsigned 8-bit integer, typical for PNG/JPG). Pixels for which one or more bands are saturated are set to zero. |
Source code in massipipe/utils.py
read_envi(header_path, image_path=None, write_byte_order_if_missing=True)
Load image in ENVI format, including wavelength vector and other metadata.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
header_path
|
Path or str
|
Path to ENVI file header. |
required |
image_path
|
Path or str or None
|
Path to ENVI data file, useful if data file is not found automatically from header file name (see spectral.io.envi.open). |
None
|
write_byte_order_if_missing
|
bool
|
Flag to indicate if the string "byte order = 0" should be written to the header file in case of MissingEnviHeaderParameter error (byte order is required by the "spectral" library, but is missing in some Resonon ENVI files). |
True
|
Returns:
Name | Type | Description |
---|---|---|
image |
NDArray
|
Image, shape (n_lines, n_samples, n_channels). |
wl |
NDArray
|
Wavelength vector, shape (n_channels,). None if no wavelengths listed. |
metadata |
dict
|
Image metadata (ENVI header content). |
Source code in massipipe/utils.py
read_envi_header(header_path)
Read ENVI header information and convert wavelengths to numeric array.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
header_path
|
Union[Path, str]
|
Path to ENVI header. |
required |
Returns:
Name | Type | Description |
---|---|---|
metadata |
dict
|
All header information formatted as dict. |
wl |
NDArray
|
If "wavelength" is present in header file, wavelengths are returned as numeric array. If not, an empty array is returned. |
Source code in massipipe/utils.py
read_json(json_path)
Read data saved in JSON file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
json_path
|
Union[Path, str]
|
Path to JSON file. |
required |
Returns:
Type | Description |
---|---|
dict
|
Data from JSON file. |
Source code in massipipe/utils.py
rgb_subset_from_hsi(hyspec_im, hyspec_wl, rgb_target_wl=(650, 550, 450))
Extract 3 bands from hyperspectral image representing red, green, blue.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
hyspec_im
|
NDArray
|
Hyperspectral image, shape (n_lines, n_samples, n_bands). |
required |
hyspec_wl
|
NDArray
|
Wavelengths for each band of hyperspectral image, in nm. Shape (n_bands,). |
required |
rgb_target_wl
|
ArrayLike
|
Wavelengths (in nm) representing red, green and blue. |
(650, 550, 450)
|
Returns:
Name | Type | Description |
---|---|---|
rgb_im |
NDArray
|
3-band image representing red, green and blue color (in that order). |
rgb_wl |
NDArray
|
3-element vector with wavelengths (in nm) corresponding to each band of rgb_im. Values correspond to the wavelengths in hyspec_wl that are closest to rgb_target_wl. |
Source code in massipipe/utils.py
save_envi(header_path, image, metadata, **kwargs)
Save ENVI file with parameters compatible with Spectronon.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
header_path
|
Union[Path, str]
|
Path to header file. Data file will be saved in the same location and with the same name, but without the '.hdr' extension. |
required |
image
|
NDArray
|
Hyperspectral image, shape (n_lines, n_samples, n_bands). |
required |
metadata
|
dict
|
Dict containing (updated) image metadata. See read_envi(). |
required |
**kwargs
|
dict
|
Additional keyword arguments passed to spectral.envi.save_image. |
{}
|
Source code in massipipe/utils.py
save_png(rgb_image, png_path)
Save RGB image as PNG using rasterio / GDAL.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
rgb_image
|
NDArray, dtype=uint8
|
Image, shape (n_lines, n_samples, n_bands=3). Image bands must be ordered as RGB (band index 0 = red, band index 1 = green, band index 2 = blue). The image must already be scaled to uint8 values 0-255. |
required |
png_path
|
Union[Path, str]
|
Path to output PNG file. |
required |
Source code in massipipe/utils.py
savitzky_golay_filter(image, window_length=13, polyorder=3, axis=2)
Filter hyperspectral image using Savitzky-Golay filter.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
image
|
NDArray
|
Image array, shape (n_lines, n_samples, n_bands). |
required |
window_length
|
int
|
Length of "local" window within which a polynomial is fitted to the data. |
13
|
polyorder
|
int
|
Order of fitted polynomial. |
3
|
axis
|
int
|
Axis along which filtering is applied. |
2
|
Returns:
Type | Description |
---|---|
NDArray
|
Filtered version of image. |
Source code in massipipe/utils.py
write_envi_header(header_path, metadata)
Write metadata dictionary to ENVI header (simple wrapper).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
header_path
|
Union[Path, str]
|
Path to ENVI header file. |
required |
metadata
|
dict
|
Metadata dictionary to write to the header file. |
required |