EcohydrologyTeam / ClearWater-modules

A collection of water quality and vegetation process simulation modules designed to couple with water transport models.
MIT License
5 stars 1 forks source link

tsm instantiation in a jupyter notebook #63

Closed imscw95 closed 8 months ago

imscw95 commented 11 months ago

I am having trouble figuring out how to instantiate the tsm model. I am running the following jupyter notebook cell, and this is returning an empty list of variables. What is the right way to do this?

image image

xaviernogueira commented 11 months ago

That seems very odd. From what I see in the images everything looks perfect.

In cells not pictured, could any of the dictionaries be getting changed? For sanity mind printing out all the inputs right before the Energy budget is instantiated and sending them on this thread.

I'd need to see that the inputs are 100% as expected as a first step.

imscw95 commented 11 months ago

I restarted the kernel and am now, seeing NameError: name 'EnergyBudget' is not defined.

image

I thought my EnergyBudget class was defined when imported in the file model.py image

xaviernogueira commented 11 months ago

@imscw95 so the lines under EnergyBudget tell you that VSCode doesn't know where it comes from. While you are correct about where's it's defined in the modules, in your script you are importing the modules and need to either import EnergyBudget explicitly or import TSM.

Something like from clearwater_modules.tsm important EnergyBudget

Or

import clearwater_modules.tsm as tsm

#then later
tsm.EnergyBudget
imscw95 commented 11 months ago

Great ok I have it working now thank you for the help!

However, the EnergyBudget init method doesn't register the static_variable_values argument. It works when I set that argument name to updateable_static_variables. I would have thought that EnergyBudget would inherit that init argument, right?

xaviernogueira commented 11 months ago

This is due to "functional overloading" if you think back to the OOP course. EnergyBudget is a "child" of base.Model. and in Python you can inherit but "overload"/overwrite any of the inherited functions by using the name name. For example if I wanted to replace the logic for ".get_state_variables()" for only one subclass/child of base.Model I could just write a new version in the subclass.

So in this case we overrode the init, but use super() to run the original/base.Model version. Because of this there can be different input arguments.

EnergyBudget takes "meteo_static_variables" and "temp_static_variables" as arguments instead of "static_variable_values", parses that a bit, combines them, and passed that as "static_variable_values" when we do super().__init__.

The different signatures for reference:

base.Model init.

class Model(CanRegisterVariable):
    _variables: list[Variable] = []

    def __init__(
        self,
        initial_state_values: Optional[InitialVariablesDict] = None,
        static_variable_values: Optional[InitialVariablesDict] = None,
        updateable_static_variables: Optional[list[str]] = None,
        track_dynamic_variables: bool = True,
        hotstart_dataset: Optional[xr.Dataset] = None,
        time_dim: Optional[str] = None,
    ) -> None:
        """Initialize the model, should be accessed by subclasses.

EnergyBudget:

class EnergyBudget(base.Model):
    """"""
    _variables: list[base.Variable] = []

    def __init__(
        self,
        initial_state_values: Optional[base.InitialVariablesDict] = None,
        updateable_static_variables: Optional[list[str]] = None,
        meteo_parameters: Optional[dict[str, float]] = None,
        temp_parameters: Optional[dict[str, float]] = None,
        use_sed_temp: bool = True,
        track_dynamic_variables: bool = True,
        hotstart_dataset: Optional[xr.Dataset] = None,
        time_dim: Optional[str] = None,
    ) -> None:
imscw95 commented 11 months ago

I see thank you!