def get_value(self, ctx, thread_id=None):
        node_state = cython.declare(NodeState)
        node_state = self._get_state(ctx)

        # return the cached value if the node isn't dirty
        if node_state.dirty_flags == DIRTY_FLAGS_NONE:
            if _trace_enabled:
                _logger.debug("Have cached value for %s[%s]" % (self.name, ctx))
            return self._get_cached_value_and_date(ctx, node_state)[0]

        # get the alt context this node should be evaluated in (i.e. the least shifted context
        # with all the shifts this node depends on).
        alt_ctx = cython.declare(MDFContext)
        alt_ctx = self.get_alt_context(ctx)

        # check the alt_ctx hasn't changed if it's been reset since last time
        if node_state.prev_alt_context is not None and node_state.prev_alt_context is not alt_ctx:
            raise ConditionalDependencyError(self, ctx, node_state.prev_alt_context, alt_ctx)

        try:
            # get the value from alt_ctx if its different from the current context
            if alt_ctx is not ctx:
                return alt_ctx._get_node_value(self, self, ctx, thread_id)

            override = cython.declare(MDFNode)
            override = self._get_override(ctx, node_state)
            if override is not None:
                value = ctx._get_node_value(override, self, ctx, thread_id)
                self._set_value(ctx, node_state, value)
                return value

            # otherwise call the subclass's _get_value method
            value = self._get_value(ctx, node_state)
            self._set_value(ctx, node_state, value)
            return value
        except:
            # Clear all dirty flags
            self._touch(node_state, DIRTY_FLAGS_ALL, True)

            # Set the error flag
            self._set_dirty(node_state, DIRTY_FLAGS_ERR, 0)
            
            # and re-raise
            raise

        finally:
            # If nothing's changed this is a cheap operation as the alt_context is cached
            new_alt_ctx = cython.declare(MDFContext)
            new_alt_ctx = self.get_alt_context(ctx)

            # check the alt_context hasn't changed after getting the value
            # on the alt_context. This could happen is a new dependency was
            # introduced that made this node dependent on any of the shifted
            # nodes between ctx and alt_ctx.
            if alt_ctx is not ctx and new_alt_ctx is not alt_ctx:
                # if this error happens often it might be worth just re-evaluating in the
                # new alt_ctx, but that would result in wasted valuations that could be
                # avoided in most cases I imagine.
                raise ConditionalDependencyError(self, ctx, alt_ctx, new_alt_ctx)

            # remember the alt_context for next time
            node_state.prev_alt_context = new_alt_ctx
returns the value for this node for a given context.
dataset/ETHPy150Open manahl/mdf/mdf/nodes.py/MDFNode.get_value