# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/geometry.ipynb.

# %% auto 0
__all__ = ['GeorectifyDatacube']

# %% ../nbs/api/geometry.ipynb 4
from fastcore.foundation import patch
from fastcore.meta import delegates
import numpy as np
import ctypes
import matplotlib.pyplot as plt
import warnings
from tqdm import tqdm
from numpy.linalg import norm
from functools import reduce
import psutil

# %% ../nbs/api/geometry.ipynb 5
from .data import *
from .capture import ProcessDatacube

# %% ../nbs/api/geometry.ipynb 6
class GeorectifyDatacube(ProcessDatacube):
    """Georectifify datacubes collected using the OpenHSI system."""
    def __init__(self, fname:str,   # path to a datacube
                 DEM_path:str=None, # path to DEM file
                 warn_mem_use:bool=True, # Give a warning if trying to allocate too much memory (> 80% of available RAM)
                ):
        """Load the elevation model at `DEM_path`. """
        self.fname = fname
        self.buff = DataCube()
        self.buff.load_nc(fname)
        if hasattr(self.buff,"ds_temperatures"):
            self.get_temp = lambda: -999 # this function needs to exist to create temperature buffer

        self.n_lines = self.buff.dc.data.shape[1]
        self.proc_lvl = -1
        self.timestamps = DateTimeBuffer(self.n_lines)
        
        if callable(getattr(self,"get_temp",None)):
            self.cam_temperatures = CircArrayBuffer(size=(self.n_lines,),dtype=np.float32)
        
        # calculate output datacube shape for preallocation!!!
        # must match cross-track, along-track, wavelength coordinates
        # will parse each along-track line and save the corresponding cross-track, wavelength 2D array
        self.dc_shape = (self.buff.dc.data.shape[0],self.n_lines,self.buff.dc.data.shape[2])
        mem_sz = 4*reduce(lambda x,y: x*y, self.dc_shape)/2**20 # MB
        mem_thresh = 0.8*psutil.virtual_memory().available/2**20 # 80% of available memory in MB
        if warn_mem_use and mem_sz > mem_thresh and input(f"{mem_sz:.02f} MB of RAM will be allocated. You have {mem_thresh/.8:.2f} MB available. Continue? [y/n]") != "y":
            raise RuntimeError(f"""Datacube memory allocation ({mem_sz:.02f} MB) exceeded >80% available RAM ({mem_thresh/.8:.2f} MB).
            Halted by user (did not receive `y` at prompt).
            To proceed, you can let `warn_mem_use=False`, decrease `n_lines`, use a `processing_lvl`>=2
            that includes binning, or continue anyway by entering `y` at the prompt.""")
        if self.dc_shape[0] > 1: print(f"Allocated {mem_sz:.02f} MB of RAM. There was {mem_thresh/.8:.2f} MB available.")
        self.dc = CircArrayBuffer(size=self.dc_shape, axis=1, dtype=np.float32)
        
        if DEM_path: self.DEM = 1
        
