import numpy as np
import pandas as pd
"""
This function converts a hyperspectral cube into a "flattened" data frame,
with one spectrum per row.
The cube is assumed to have two spatial dimensions followed by a spectral
dimension: x,y,wvl.
"""
[docs]
def cube_to_df(cube, wvls, spect_label="wvl", meta_label="meta"):
# make multiindexed column names for wvls
cols = pd.MultiIndex.from_tuples([(spect_label, i) for i in wvls])
# make x coordinates
x_2d = np.zeros((cube.shape[0], cube.shape[1]))
for n in range(cube.shape[0]):
x_2d[n, :] = n
# make y coordinates
y_2d = np.zeros((cube.shape[0], cube.shape[1]))
for n in range(cube.shape[1]):
y_2d[:, n] = n
# stack the x and y coordinates onto the data
coords = np.transpose(np.vstack([[x_2d], [y_2d]]), (1, 2, 0))
combined_array = np.zeros((cube.shape[0], cube.shape[1], cube.shape[2] + 2))
combined_array[:, :, :-2] = cube
combined_array[:, :, -2:] = coords
cols = cols.append(
pd.MultiIndex.from_tuples([(meta_label, "x"), (meta_label, "y")])
)
# reshape the cube into a table and put that into a data frame
df = pd.DataFrame(
np.reshape(
combined_array,
(
combined_array.shape[0] * combined_array.shape[1],
combined_array.shape[2],
),
order="C",
),
columns=cols,
)
return df
[docs]
def df_to_cube(df, spect_label="wvl", meta_label="meta", cube_shape=None):
if cube_shape is None: # If shape is not specified, try to get it from
# the range of x and y values in the df
cube_shape = (
int(np.max(df[meta_label, "x"]) + 1),
int(np.max(df[meta_label, "y"]) + 1),
-1,
)
cube = df[spect_label].values.reshape(cube_shape)
return cube
[docs]
def df_parameter_to_2d(df, parameter_name, meta_label="meta", shape_2d=None):
if shape_2d is None: # If shape is not specified, try to get it from
# the range of x and y values in the df
shape_2d = (
int(np.max(df[meta_label, "x"]) + 1),
int(np.max(df[meta_label, "y"]) + 1),
-1,
)
param_2d = np.squeeze(df[("parameter", parameter_name)].values.reshape(shape_2d))
return param_2d
if __name__ == "__main__":
wvls = np.array(range(1000))
cube = np.random.randn(300, 400, 1000)
df = cube_to_df(cube, wvls)
cube2 = df_to_cube(df)