def __init__(self, reference_converter=None, types_printer=None): # type: (IReferenceConverter,TypesPrinter) -> None # todo by kp: this should expect a ITypesPrinter as the second arg self.reference_converter = LatexReferenceConverter() if types_printer is not None: self.types_printer = types_printer else: self.types_printer = TypesPrinter()
def __init__(self, reference_converter: IReferenceConverter = None, types_printer: TypesPrinter = None): self.reference_converter = LatexReferenceConverter() if types_printer is not None: self.types_printer = types_printer else: self.types_printer = LatexTypesPrinter()
def setup_model_generation_helpers(self, neuron: ASTNeuron): """ Returns a namespace for Jinja2 neuron model documentation template. :param neuron: a single neuron instance :type neuron: ASTNeuron :return: a map from name to functionality. :rtype: dict """ converter = LatexReferenceConverter() latex_expression_printer = LatexExpressionPrinter(converter) namespace = dict() namespace['now'] = datetime.datetime.utcnow() namespace['neuron'] = neuron namespace['neuronName'] = str(neuron.get_name()) namespace['printer'] = NestPrinter(latex_expression_printer) namespace['assignments'] = NestAssignmentsHelper() namespace['names'] = NestNamesConverter() namespace['declarations'] = NestDeclarationsHelper() namespace['utils'] = ASTUtils() namespace['odeTransformer'] = OdeTransformer() import textwrap pre_comments_bak = neuron.pre_comments neuron.pre_comments = [] namespace['neuron_source_code'] = textwrap.indent( neuron.__str__(), " ") neuron.pre_comments = pre_comments_bak return namespace
def setup_index_generation_helpers(self, neurons: List[ASTNeuron]): """ Returns a namespace for Jinja2 neuron model index page template. :param neurons: a list of neuron instances :type neurons: List[ASTNeuron] :return: a map from name to functionality. :rtype: dict """ converter = LatexReferenceConverter() latex_expression_printer = LatexExpressionPrinter(converter) namespace = dict() namespace['now'] = datetime.datetime.utcnow() namespace['neurons'] = neurons namespace['neuronNames'] = [ str(neuron.get_name()) for neuron in neurons ] namespace['printer'] = NestPrinter(latex_expression_printer) namespace['assignments'] = NestAssignmentsHelper() namespace['names'] = NestNamesConverter() namespace['declarations'] = NestDeclarationsHelper() namespace['utils'] = ASTUtils() namespace['odeTransformer'] = OdeTransformer() return namespace
class LatexExpressionPrinter(): """ Pretty printer for LaTeX. Assumes to be printing in a LaTeX environment where math mode is already on. """ def __init__(self, reference_converter=None, types_printer=None): # type: (IReferenceConverter,TypesPrinter) -> None # todo by kp: this should expect a ITypesPrinter as the second arg self.reference_converter = LatexReferenceConverter() if types_printer is not None: self.types_printer = types_printer else: self.types_printer = TypesPrinter() def print_expression(self, node): # type: (ASTExpressionNode) -> str return self.__do_print(node) if node.get_implicit_conversion_factor() is not None: return str(node.get_implicit_conversion_factor() ) + ' * (' + self.__do_print(node) + ')' else: return self.__do_print(node) def __do_print(self, node): # type: (ASTExpressionNode) -> str if isinstance(node, ASTVariable): return self.reference_converter.convert_name_reference(node) elif isinstance(node, ASTSimpleExpression): if node.has_unit(): # todo by kp: this should not be done in the typesPrinter, obsolete s = "" if node.get_numeric_literal() != 1: s += "{0:E}".format(node.get_numeric_literal()) s += r"\cdot" s += self.reference_converter.convert_name_reference( node.get_variable()) return s elif node.is_numeric_literal(): return str(node.get_numeric_literal()) elif node.is_inf_literal: return r"\infty" elif node.is_string(): return self.types_printer.pretty_print(node.get_string()) elif node.is_boolean_true: return self.types_printer.pretty_print(True) elif node.is_boolean_false: return self.types_printer.pretty_print(False) elif node.is_variable(): return self.reference_converter.convert_name_reference( node.get_variable()) elif node.is_function_call(): return self.print_function_call(node.get_function_call()) elif isinstance(node, ASTExpression): # a unary operator if node.is_unary_operator(): op = self.reference_converter.convert_unary_op( node.get_unary_operator()) rhs = self.print_expression(node.get_expression()) return op % rhs # encapsulated in brackets elif node.is_encapsulated: return self.reference_converter.convert_encapsulated( ) % self.print_expression(node.get_expression()) # logical not elif node.is_logical_not: op = self.reference_converter.convert_logical_not() rhs = self.print_expression(node.get_expression()) return op % rhs # compound rhs with lhs + rhs elif node.is_compound_expression(): lhs = self.print_expression(node.get_lhs()) rhs = self.print_expression(node.get_rhs()) wide = False if node.get_binary_operator().is_div_op \ and len(lhs) > 3 * len(rhs): # if lhs (numerator) is much wider than rhs (denominator), rewrite as a factor wide = True op = self.reference_converter.convert_binary_op( node.get_binary_operator(), wide=wide) return op % ({"lhs": lhs, "rhs": rhs}) elif node.is_ternary_operator(): condition = self.print_expression(node.get_condition()) if_true = self.print_expression(node.get_if_true()) if_not = self.print_expression(node.if_not) return self.reference_converter.convert_ternary_operator() % ( condition, if_true, if_not) else: raise RuntimeError('Unsupported rhs in rhs pretty printer!') def print_function_call(self, function_call): # type: (ASTFunctionCall) -> str function_name = self.reference_converter.convert_function_call( function_call) if ASTUtils.needs_arguments(function_call): return function_name % self.print_function_call_argument_list( function_call) else: return function_name def print_function_call_argument_list(self, function_call): # type: (ASTFunctionCall) -> tuple of str ret = [] for arg in function_call.get_args(): ret.append(self.print_expression(arg)) return tuple(ret)