Exemple #1
0
    def apply(self, functions, x, xstart, xstop, y, ystart, ystop, evaluation, options):
        "%(name)s[functions_, {x_Symbol, xstart_, xstop_}, {y_Symbol, ystart_, ystop_}, OptionsPattern[%(name)s]]"
        xexpr_limits = Expression("List", x, xstart, xstop)
        yexpr_limits = Expression("List", y, ystart, ystop)
        expr = Expression(self.get_name(), functions, xexpr_limits, yexpr_limits, *options_to_rules(options))

        functions = self.get_functions_param(functions)
        plot_name = self.get_name()

        x_name = x.get_name()
        y_name = y.get_name()

        try:
            xstart, xstop, ystart, ystop = [
                value.to_number(n_evaluation=evaluation) for value in (xstart, xstop, ystart, ystop)
            ]
        except NumberError, exc:
            expr = Expression(
                plot_name,
                functions,
                Expression("List", x, xstart, xstop),
                Expression("List", y, ystart, ystop),
                *options_to_rules(options)
            )
            evaluation.message(plot_name, "plln", value, expr)
            return
Exemple #2
0
    def apply(self, functions, x, xstart, xstop, y, ystart, ystop, evaluation,
              options):
        '%(name)s[functions_, {x_Symbol, xstart_, xstop_}, {y_Symbol, ystart_, ystop_}, OptionsPattern[%(name)s]]'
        xexpr_limits = Expression('List', x, xstart, xstop)
        yexpr_limits = Expression('List', y, ystart, ystop)
        expr = Expression(self.get_name(), functions, xexpr_limits,
                          yexpr_limits, *options_to_rules(options))

        functions = self.get_functions_param(functions)
        plot_name = self.get_name()

        x_name = x.get_name()
        y_name = y.get_name()

        try:
            xstart, xstop, ystart, ystop = [
                value.to_number(n_evaluation=evaluation)
                for value in (xstart, xstop, ystart, ystop)
            ]
        except NumberError, exc:
            expr = Expression(plot_name, functions,
                              Expression('List', x, xstart, xstop),
                              Expression('List', y, ystart, ystop),
                              *options_to_rules(options))
            evaluation.message(plot_name, 'plln', value, expr)
            return
Exemple #3
0
 def apply(self, functions, x, start, stop, evaluation, options):
     'Plot[functions_, {x_Symbol, start_, stop_}, OptionsPattern[Plot]]'
     
     expr = Expression('Plot', functions, Expression('List', x, start, stop), *options_to_rules(options))
     if functions.has_form('List', None):
         functions = functions.leaves
     else:
         functions = [functions]
     x = x.get_name()
     try:
         start = start.to_number(n_evaluation=evaluation)
     except NumberError:
         evaluation.message('Plot', 'plln', start, expr)
         return
     try:
         stop = stop.to_number(n_evaluation=evaluation)
     except NumberError:
         evaluation.message('Plot', 'plln', stop, expr)
         return
         
     def eval_f(f, x_value):
         value = dynamic_scoping(f.evaluate, {x: x_value}, evaluation)
         value = chop(value).get_real_value()
         return value
     
     hue = 0.67
     hue_pos = 0.236068
     hue_neg = -0.763932
     
     graphics = []
     for index, f in enumerate(functions):
         points = []
         continuous = False
         steps = 50
         d = (stop - start) / steps
         for index in range(steps + 1):
             x_value = start + index * d
             y = eval_f(f, Real(x_value))
             if y is not None:
                 point = (x_value, y)
                 if continuous:
                     points[-1].append(point)
                 else:
                     points.append([point])
                 continuous = True
             else:
                 continuous = False    
         graphics.append(Expression('Hue', hue, 0.6, 0.6))
         graphics.append(Expression('Line', Expression('List', *(Expression('List',
             *(Expression('List', Real(x), Real(y)) for x, y in line)) for line in points)
         )))
         
         if index % 4 == 0:
             hue += hue_pos
         else:
             hue += hue_neg
         if hue > 1: hue -= 1
         if hue < 0: hue += 1
     
     return Expression('Graphics', Expression('List', *graphics), *options_to_rules(options))
Exemple #4
0
    def apply_makeboxes(self, content, evaluation, options):
        """MakeBoxes[%(name)s[content_, OptionsPattern[%(name)s]],
        StandardForm|TraditionalForm|OutputForm]"""
        def convert(content):
            head = content.get_head_name()

            if head == "System`List":
                return Expression(SymbolList,
                                  *[convert(item) for item in content.leaves])
            elif head == "System`Style":
                return Expression("StyleBox",
                                  *[convert(item) for item in content.leaves])

            if head in element_heads:
                if head == "System`Text":
                    head = "System`Inset"
                atoms = content.get_atoms(include_heads=False)
                if any(not isinstance(atom, (Integer, Real))
                       and not atom.get_name() in GRAPHICS_SYMBOLS
                       for atom in atoms):
                    if head == "System`Inset":
                        inset = content.leaves[0]
                        if inset.get_head_name() == "System`Graphics":
                            opts = {}
                            # opts = dict(opt._leaves[0].name:opt_leaves[1]   for opt in  inset._leaves[1:])
                            inset = self.apply_makeboxes(
                                inset._leaves[0], evaluation, opts)
                        n_leaves = [inset] + [
                            Expression(SymbolN, leaf).evaluate(evaluation)
                            for leaf in content.leaves[1:]
                        ]
                    else:
                        n_leaves = (Expression(SymbolN,
                                               leaf).evaluate(evaluation)
                                    for leaf in content.leaves)
                else:
                    n_leaves = content.leaves
                return Expression(head + self.box_suffix, *n_leaves)
            return content

        for option in options:
            if option not in ("System`ImageSize", ):
                options[option] = Expression(
                    SymbolN, options[option]).evaluate(evaluation)

        from mathics.builtin.box.graphics import GraphicsBox
        from mathics.builtin.box.graphics3d import Graphics3DBox
        from mathics.builtin.drawing.graphics3d import Graphics3D

        if type(self) is Graphics:
            return GraphicsBox(convert(content),
                               evaluation=evaluation,
                               *options_to_rules(options))
        elif type(self) is Graphics3D:
            return Graphics3DBox(convert(content),
                                 evaluation=evaluation,
                                 *options_to_rules(options))
Exemple #5
0
    def apply_elements(self, filename, elements, evaluation, options={}):
        'Import[filename_, elements_List?(AllTrue[#, NotOptionQ]&), OptionsPattern[]]'
        # Check filename
        path = filename.to_python()
        if not (isinstance(path, str) and path[0] == path[-1] == '"'):
            evaluation.message('Import', 'chtype', filename)
            return Symbol('$Failed')

        # Download via URL
        if isinstance(filename, String):
            if any(filename.get_string_value().startswith(prefix)
                   for prefix in ('http://', 'https://', 'ftp://')):
                return Expression('FetchURL', filename, elements,
                                  *options_to_rules(options))

        # Load local file
        findfile = Expression('FindFile', filename).evaluate(evaluation)

        if findfile == Symbol('$Failed'):
            evaluation.message('Import', 'nffil')
            return findfile

        def determine_filetype():
            return Expression(
                'FileFormat',
                findfile).evaluate(evaluation=evaluation).get_string_value()

        return self._import(findfile, determine_filetype, elements, evaluation,
                            options)
Exemple #6
0
 def apply(self, f, x, xstart, xstop, y, ystart, ystop, evaluation, options):
     'DensityPlot[f_, {x_Symbol, xstart_, xstop_}, {y_Symbol, ystart_, ystop_}, OptionsPattern[DensityPlot]]'
     
     x = x.get_name()
     y = y.get_name()
     
     color_function = self.get_option(options, 'ColorFunction', evaluation, pop=True)
     color_function_scaling = self.get_option(options, 'ColorFunctionScaling', evaluation, pop=True)
     
     color_function_min = color_function_max = None
     if color_function.get_name() == 'Automatic':
         color_function = String('LakeColors')
     if color_function.get_string_value():
         func = Expression('ColorData', color_function.get_string_value()).evaluate(evaluation)
         if func.has_form('ColorDataFunction', 4):
             color_function_min = func.leaves[2].leaves[0].get_real_value()
             color_function_max = func.leaves[2].leaves[1].get_real_value()
             color_function = Expression('Function', Expression(func.leaves[3], Expression('Slot', 1)))
         else:
             evaluation.message('DensityPlot', 'color', func)
             return
     if color_function.has_form('ColorDataFunction', 4):
         color_function_min = color_function.leaves[2].leaves[0].get_real_value()
         color_function_max = color_function.leaves[2].leaves[1].get_real_value()
         
     color_function_scaling = color_function_scaling.is_true()
         
     try:
         xstart, xstop, ystart, ystop = [value.to_number(n_evaluation=evaluation) for value in
             (xstart, xstop, ystart, ystop)]
     except NumberError, exc:
         expr = Expression('DensityPlot', f, Expression('List', x, xstart, xstop),
             Expression('List', y, ystart, ystop), *options_to_rules(options))
         evaluation.message('DensityPlot', 'plln', exc.value, expr)
         return
Exemple #7
0
 def apply_makeboxes(self, array, f, evaluation, options):
     'MakeBoxes[Grid[array_?MatrixQ, OptionsPattern[Grid]], f:StandardForm|TraditionalForm|OutputForm]'
     
     array = Expression('List', *(Expression('List', *(Expression('MakeBoxes', item, f)
         for item in row.leaves)) for row in array.leaves))
     
     return Expression('GridBox', array, *options_to_rules(options))
Exemple #8
0
    def apply_elements(self, filename, elements, evaluation, options={}):
        'Import[filename_, elements_List?(AllTrue[#, NotOptionQ]&), OptionsPattern[]]'
        # Check filename
        path = filename.to_python()
        if not (isinstance(path, six.string_types) and path[0] == path[-1] == '"'):
            evaluation.message('Import', 'chtype', filename)
            return Symbol('$Failed')

        # Download via URL
        if isinstance(filename, String):
            if any(filename.get_string_value().startswith(prefix) for prefix in ('http://', 'https://', 'ftp://')):
                return Expression('FetchURL', filename, elements, *options_to_rules(options))

        # Load local file
        findfile = Expression('FindFile', filename).evaluate(evaluation)

        if findfile == Symbol('$Failed'):
            evaluation.message('Import', 'nffil')
            return findfile

        def determine_filetype():
            return Expression('FileFormat', findfile).evaluate(
                evaluation=evaluation).get_string_value()

        return self._import(findfile, determine_filetype, elements, evaluation, options)
Exemple #9
0
 def apply_makeboxes(self, content, evaluation, options):
     'MakeBoxes[Graphics[content_, OptionsPattern[Graphics]], StandardForm|TraditionalForm]'
     
     def convert(content):
         if content.has_form('List', None):
             return Expression('List', *[convert(item) for item in content.leaves])
         head = content.get_head_name()
         if head in element_heads:
             if head == 'Text':
                 head = 'Inset'
             atoms = content.get_atoms(include_heads=False)
             #print atoms
             #for atom in atoms:
             #    if not isinstance(atom, (Integer, Real)) and not atom.get_name() in GRAPHICS_SYMBOLS:
             #        print atom
             if any(not isinstance(atom, (Integer, Real)) and not atom.get_name() in GRAPHICS_SYMBOLS for atom in atoms):
                 if head == 'Inset':
                     n_leaves = [content.leaves[0]] + [Expression('N', leaf).evaluate(evaluation) for leaf in content.leaves[1:]]
                 else:
                     n_leaves = (Expression('N', leaf).evaluate(evaluation) for leaf in content.leaves)
             else:
                 n_leaves = content.leaves
             return Expression(head + 'Box', *n_leaves)
         return content
     
     for option in options:
         options[option] = Expression('N', options[option]).evaluate(evaluation)
     return Expression('GraphicsBox', convert(content), *options_to_rules(options))
Exemple #10
0
    def apply_makeboxes(self, array, f, evaluation, options):
        'MakeBoxes[Grid[array_?MatrixQ, OptionsPattern[Grid]], f:StandardForm|TraditionalForm|OutputForm]'

        array = Expression(
            'List',
            *(Expression(
                'List',
                *(Expression('MakeBoxes', item, f) for item in row.leaves))
              for row in array.leaves))

        return Expression('GridBox', array, *options_to_rules(options))
Exemple #11
0
    def apply(self, f, x, xstart, xstop, y, ystart, ystop, evaluation,
              options):
        'DensityPlot[f_, {x_Symbol, xstart_, xstop_}, {y_Symbol, ystart_, ystop_}, OptionsPattern[DensityPlot]]'

        x = x.get_name()
        y = y.get_name()

        color_function = self.get_option(options,
                                         'ColorFunction',
                                         evaluation,
                                         pop=True)
        color_function_scaling = self.get_option(options,
                                                 'ColorFunctionScaling',
                                                 evaluation,
                                                 pop=True)

        color_function_min = color_function_max = None
        if color_function.get_name() == 'Automatic':
            color_function = String('LakeColors')
        if color_function.get_string_value():
            func = Expression(
                'ColorData',
                color_function.get_string_value()).evaluate(evaluation)
            if func.has_form('ColorDataFunction', 4):
                color_function_min = func.leaves[2].leaves[0].get_real_value()
                color_function_max = func.leaves[2].leaves[1].get_real_value()
                color_function = Expression(
                    'Function',
                    Expression(func.leaves[3], Expression('Slot', 1)))
            else:
                evaluation.message('DensityPlot', 'color', func)
                return
        if color_function.has_form('ColorDataFunction', 4):
            color_function_min = color_function.leaves[2].leaves[
                0].get_real_value()
            color_function_max = color_function.leaves[2].leaves[
                1].get_real_value()

        color_function_scaling = color_function_scaling.is_true()

        try:
            xstart, xstop, ystart, ystop = [
                value.to_number(n_evaluation=evaluation)
                for value in (xstart, xstop, ystart, ystop)
            ]
        except NumberError, exc:
            expr = Expression('DensityPlot', f,
                              Expression('List', x, xstart, xstop),
                              Expression('List', y, ystart, ystop),
                              *options_to_rules(options))
            evaluation.message('DensityPlot', 'plln', exc.value, expr)
            return
Exemple #12
0
    def apply_makeboxes(self, array, f, evaluation, options):
        """MakeBoxes[Grid[array_?MatrixQ, OptionsPattern[Grid]],
            f:StandardForm|TraditionalForm|OutputForm]"""

        return Expression(
            "GridBox",
            Expression(
                "List",
                *(
                    Expression("List", *(Expression("MakeBoxes", item, f) for item in row.leaves))
                    for row in array.leaves
                )
            ),
            *options_to_rules(options)
        )
Exemple #13
0
    def apply(self, graphics, evaluation, options):
        """Show[graphics_, OptionsPattern[%(name)s]]"""

        for option in options:
            if option not in ("System`ImageSize",):
                options[option] = Expression(SymbolN, options[option]).evaluate(
                    evaluation
                )

        # The below could probably be done with graphics.filter..
        new_leaves = []
        options_set = set(options.keys())
        for leaf in graphics.leaves:
            leaf_name = leaf.get_head_name()
            if leaf_name == "System`Rule" and str(leaf.leaves[0]) in options_set:
                continue
            new_leaves.append(leaf)

        new_leaves += options_to_rules(options)
        graphics = graphics.restructure(graphics.head, new_leaves, evaluation)

        return graphics
Exemple #14
0
    def apply(self, functions, x, start, stop, evaluation, options):
        '''%(name)s[functions_, {x_Symbol, start_, stop_},
            OptionsPattern[%(name)s]]'''

        expr_limits = Expression('List', x, start, stop)
        expr = Expression(self.get_name(), functions, expr_limits,
                          *options_to_rules(options))
        functions = self.get_functions_param(functions)
        x_name = x.get_name()

        try:
            start = start.to_number(n_evaluation=evaluation)
        except NumberError:
            evaluation.message(self.get_name(), 'plln', start, expr)
            return
        try:
            stop = stop.to_number(n_evaluation=evaluation)
        except NumberError:
            evaluation.message(self.get_name(), 'plln', stop, expr)
            return
        if start >= stop:
            evaluation.message(self.get_name(), 'plld', expr_limits)
            return

        # PlotRange Option
        def check_range(range):
            if range in ('Automatic', 'All'):
                return True
            if isinstance(range, list) and len(range) == 2:
                if (isinstance(range[0], numbers.Real) and  # noqa
                    isinstance(range[1], numbers.Real)):
                    return True
            return False
        plotrange_option = self.get_option(options, 'PlotRange', evaluation)
        plotrange = plotrange_option.to_python(n_evaluation=evaluation)
        x_range, y_range = self.get_plotrange(plotrange, start, stop)
        if not check_range(x_range) or not check_range(y_range):
            evaluation.message(self.get_name(), 'prng', plotrange_option)
            x_range, y_range = [start, stop], 'Automatic'
        # x_range and y_range are now either Automatic, All, or of the form
        # [min, max]
        assert x_range in ('Automatic', 'All') or isinstance(x_range, list)
        assert y_range in ('Automatic', 'All') or isinstance(y_range, list)

        # Mesh Option
        mesh_option = self.get_option(options, 'Mesh', evaluation)
        mesh = mesh_option.to_python()
        if mesh not in ['None', 'Full', 'All']:
            evaluation.message('Mesh', 'ilevels', mesh_option)
            mesh = 'None'

        # PlotPoints Option
        plotpoints_option = self.get_option(options, 'PlotPoints', evaluation)
        plotpoints = plotpoints_option.to_python()
        if plotpoints == 'None':
            plotpoints = 57
        if not (isinstance(plotpoints, int) and plotpoints >= 2):
            return evaluation.message(self.get_name(), 'ppts', plotpoints)

        # MaxRecursion Option
        max_recursion_limit = 15
        maxrecursion_option = self.get_option(
            options, 'MaxRecursion', evaluation)
        maxrecursion = maxrecursion_option.to_python()
        try:
            if maxrecursion == 'Automatic':
                maxrecursion = 3
            elif maxrecursion == float('inf'):
                maxrecursion = max_recursion_limit
                raise ValueError
            elif isinstance(maxrecursion, int):
                if maxrecursion > max_recursion_limit:
                    maxrecursion = max_recursion_limit
                    raise ValueError
                if maxrecursion < 0:
                    maxrecursion = 0
                    raise ValueError
            else:
                maxrecursion = 0
                raise ValueError
        except ValueError:
            evaluation.message(self.get_name(), 'invmaxrec', maxrecursion,
                               max_recursion_limit)
        assert isinstance(maxrecursion, int)

        # Exclusions Option
        # TODO: Make exclusions option work properly with ParametricPlot
        def check_exclusion(excl):
            if isinstance(excl, list):
                return all(check_exclusion(e) for e in excl)
            if excl == 'Automatic':
                return True
            if not isinstance(excl, numbers.Real):
                return False
            return True

        exclusions_option = self.get_option(options, 'Exclusions', evaluation)
        exclusions = exclusions_option.to_python(n_evaluation=evaluation)
        # TODO Turn expressions into points E.g. Sin[x] == 0 becomes 0, 2 Pi...

        if exclusions in ['None', ['None']]:
            exclusions = 'None'
        elif not isinstance(exclusions, list):
            exclusions = [exclusions]

            if (isinstance(exclusions, list) and        # noqa
                all(check_exclusion(excl) for excl in exclusions)):
                pass

            else:
                evaluation.message(
                    self.get_name(), 'invexcl', exclusions_option)
                exclusions = ['Automatic']

        # exclusions is now either 'None' or a list of reals and 'Automatic'
        assert (exclusions == 'None' or isinstance(exclusions, list))

        # constants to generate colors
        hue = 0.67
        hue_pos = 0.236068
        hue_neg = -0.763932

        def get_points_minmax(points):
            xmin = xmax = ymin = ymax = None
            for line in points:
                for x, y in line:
                    if xmin is None or x < xmin:
                        xmin = x
                    if xmax is None or x > xmax:
                        xmax = x
                    if ymin is None or y < ymin:
                        ymin = y
                    if ymax is None or y > ymax:
                        ymax = y
            return xmin, xmax, ymin, ymax

        def zero_to_one(value):
            if value == 0:
                return 1
            return value

        def get_points_range(points):
            xmin, xmax, ymin, ymax = get_points_minmax(points)
            if xmin is None or xmax is None:
                xmin, xmax = 0, 1
            if ymin is None or ymax is None:
                ymin, ymax = 0, 1
            return zero_to_one(xmax - xmin), zero_to_one(ymax - ymin)

        function_hues = []
        base_plot_points = []   # list of points in base subdivision
        plot_points = []        # list of all plotted points
        mesh_points = []
        graphics = []           # list of resulting graphics primitives
        for index, f in enumerate(functions):
            points = []
            xvalues = []  # x value for each point in points
            tmp_mesh_points = []  # For this function only
            continuous = False
            d = (stop - start) / (plotpoints - 1)
            for i in xrange(plotpoints):
                x_value = start + i * d
                point = self.eval_f(f, x_name, x_value, evaluation)
                if point is not None:
                    if continuous:
                        points[-1].append(point)
                        xvalues[-1].append(x_value)
                    else:
                        points.append([point])
                        xvalues.append([x_value])
                    continuous = True
                else:
                    continuous = False

            base_points = []
            for line in points:
                base_points.extend(line)
            base_plot_points.extend(base_points)

            xmin, xmax = automatic_plot_range([xx for xx, yy in base_points])
            xscale = 1. / zero_to_one(xmax - xmin)
            ymin, ymax = automatic_plot_range([yy for xx, yy in base_points])
            yscale = 1. / zero_to_one(ymax - ymin)

            if mesh == 'Full':
                for line in points:
                    tmp_mesh_points.extend(line)

            def find_excl(excl):
                # Find which line the exclusion is in
                for l in range(len(xvalues)):  # TODO: Binary Search faster?
                    if xvalues[l][0] <= excl and xvalues[l][-1] >= excl:
                        break
                    if (xvalues[l][-1] <= excl and      # nopep8
                        xvalues[min(l + 1, len(xvalues) - 1)][0] >= excl):
                        return min(l + 1, len(xvalues) - 1), 0, False
                xi = 0
                for xi in range(len(xvalues[l]) - 1):
                    if xvalues[l][xi] <= excl and xvalues[l][xi + 1] >= excl:
                        return l, xi + 1, True
                return l, xi + 1, False

            if exclusions != 'None':
                for excl in exclusions:
                        if excl != 'Automatic':
                            l, xi, split_required = find_excl(excl)
                            if split_required:
                                xvalues.insert(l + 1, xvalues[l][xi:])
                                xvalues[l] = xvalues[l][:xi]
                                points.insert(l + 1, points[l][xi:])
                                points[l] = points[l][:xi]
                        # assert(xvalues[l][-1] <= excl  <= xvalues[l+1][0])

            # Adaptive Sampling - loop again and interpolate highly angled
            # sections

            # Cos of the maximum angle between successive line segments
            ang_thresh = cos(pi / 180)

            for line, line_xvalues in zip(points, xvalues):
                recursion_count = 0
                smooth = False
                while not smooth and recursion_count < maxrecursion:
                    recursion_count += 1
                    smooth = True
                    i = 2
                    while i < len(line):
                        vec1 = (xscale * (line[i - 1][0] - line[i - 2][0]),
                                yscale * (line[i - 1][1] - line[i - 2][1]))
                        vec2 = (xscale * (line[i][0] - line[i - 1][0]),
                                yscale * (line[i][1] - line[i - 1][1]))
                        try:
                            angle = (vec1[0] * vec2[0] + vec1[1] * vec2[1]) \
                                / sqrt((vec1[0] ** 2 + vec1[1] ** 2) *
                                       (vec2[0] ** 2 + vec2[1] ** 2))
                        except ZeroDivisionError:
                            angle = 0.0
                        if abs(angle) < ang_thresh:
                            smooth = False
                            incr = 0

                            x_value = 0.5 * (line_xvalues[i - 1] +
                                             line_xvalues[i])

                            point = self.eval_f(f, x_name, x_value, evaluation)
                            if point is not None:
                                line.insert(i, point)
                                line_xvalues.insert(i, x_value)
                                incr += 1

                            x_value = 0.5 * (line_xvalues[i - 2] +
                                             line_xvalues[i - 1])
                            point = self.eval_f(f, x_name, x_value, evaluation)
                            if point is not None:
                                line.insert(i - 1, point)
                                line_xvalues.insert(i - 1, x_value)
                                incr += 1

                            i += incr
                        i += 1

            if exclusions == 'None':    # Join all the Lines
                points = [[(xx, yy) for line in points for xx, yy in line]]

            graphics.append(Expression('Hue', hue, 0.6, 0.6))
            graphics.append(Expression('Line', from_python(points)))

            for line in points:
                plot_points.extend(line)

            if mesh == 'All':
                for line in points:
                    tmp_mesh_points.extend(line)

            if mesh != 'None':
                mesh_points.append(tmp_mesh_points)

            function_hues.append(hue)

            if index % 4 == 0:
                hue += hue_pos
            else:
                hue += hue_neg
            if hue > 1:
                hue -= 1
            if hue < 0:
                hue += 1

        x_range = get_plot_range([xx for xx, yy in base_plot_points],
                                 [xx for xx, yy in plot_points], x_range)
        y_range = get_plot_range([yy for xx, yy in base_plot_points],
                                 [yy for xx, yy in plot_points], y_range)

        options['PlotRange'] = from_python([x_range, y_range])

        if mesh != 'None':
            for hue, points in zip(function_hues, mesh_points):
                graphics.append(Expression('Hue', hue, 0.6, 0.6))
                meshpoints = [Expression('List', xx, yy) for xx, yy in points]
                graphics.append(Expression(
                    'Point', Expression('List', *meshpoints)))

        return Expression('Graphics', Expression('List', *graphics),
                          *options_to_rules(options))
Exemple #15
0
 def final_graphics(self, graphics, options):
     return Expression('Graphics', Expression('List', *graphics),
                       *options_to_rules(options))
Exemple #16
0
    def apply(self, points, evaluation, options):
        '%(name)s[points_, OptionsPattern[%(name)s]]'

        plot_name = self.get_name()
        all_points = points.to_python(n_evaluation=evaluation)
        expr = Expression(self.get_name(), points, *options_to_rules(options))

        # PlotRange Option
        def check_range(range):
            if range in ('Automatic', 'All'):
                return True
            if isinstance(range, list) and len(range) == 2:
                if (isinstance(range[0], numbers.Real) and      # noqa
                    isinstance(range[1], numbers.Real)):
                    return True
            return False

        plotrange_option = self.get_option(options, 'PlotRange', evaluation)
        plotrange = plotrange_option.to_python(n_evaluation=evaluation)
        if plotrange == 'All':
            plotrange = ['All', 'All']
        elif plotrange == 'Automatic':
            plotrange = ['Automatic', 'Automatic']
        elif isinstance(plotrange, numbers.Real):
            plotrange = [[-plotrange, plotrange], [-plotrange, plotrange]]
        elif isinstance(plotrange, list) and len(plotrange) == 2:
            if all(isinstance(pr, numbers.Real) for pr in plotrange):
                plotrange = ['All', plotrange]
            elif all(check_range(pr) for pr in plotrange):
                pass
        else:
            evaluation.message(self.get_name(), 'prng', plotrange_option)
            plotrange = ['Automatic', 'Automatic']

        x_range, y_range = plotrange[0], plotrange[1]
        assert x_range in ('Automatic', 'All') or isinstance(x_range, list)
        assert y_range in ('Automatic', 'All') or isinstance(y_range, list)

        # Filling option
        # TODO: Fill between corresponding points in two datasets:
        filling_option = self.get_option(options, 'Filling', evaluation)
        filling = filling_option.to_python(n_evaluation=evaluation)
        if (filling in ['Top', 'Bottom', 'Axis'] or     # noqa
            isinstance(filling, numbers.Real)):
            pass
        else:
            # Mathematica does not even check that filling is sane
            filling = None

        # Joined Option
        joined_option = self.get_option(options, 'Joined', evaluation)
        joined = joined_option.to_python()
        if joined not in [True, False]:
            evaluation.message(plot_name, 'joind', joined_option, expr)
            joined = False

        if isinstance(all_points, list) and len(all_points) != 0:
            if all(not isinstance(point, list) for point in all_points):
                # Only y values given
                all_points = [[[float(i + 1), all_points[i]]
                               for i in range(len(all_points))]]
            elif all(isinstance(line, list) and
                     len(line) == 2 for line in all_points):
                # Single list of (x,y) pairs
                all_points = [all_points]
            elif all(isinstance(line, list) for line in all_points):
                # List of lines
                if all(isinstance(point, list) and len(point) == 2
                       for line in all_points for point in line):
                    pass
                elif all(not isinstance(point, list)
                         for line in all_points for point in line):
                    all_points = [
                        [[float(i + 1), l] for i, l in enumerate(line)]
                        for line in all_points]
                else:
                    return
            else:
                return
        else:
            return

        # Split into segments at missing data
        all_points = [[line] for line in all_points]
        for l, line in enumerate(all_points):
            i = 0
            while i < len(all_points[l]):
                seg = line[i]
                for j, point in enumerate(seg):
                    if not ((isinstance(point[0], float) or
                             isinstance(point[0], int))
                            and (isinstance(point[1], float) or
                                 isinstance(point[1], int))):
                        all_points[l].insert(i, seg[:j])
                        all_points[l][i + 1] = seg[j + 1:]
                        i -= 1
                        break

                i += 1

        y_range = get_plot_range(
            [y for line in all_points for seg in line for x, y in seg],
            [y for line in all_points for seg in line for x, y in seg],
            y_range)
        x_range = get_plot_range(
            [x for line in all_points for seg in line for x, y in seg],
            [x for line in all_points for seg in line for x, y in seg],
            x_range)

        if filling == 'Axis':
            # TODO: Handle arbitary axis intercepts
            filling = 0.0
        elif filling == 'Bottom':
            filling = y_range[0]
        elif filling == 'Top':
            filling = y_range[1]

        hue = 0.67
        hue_pos = 0.236068
        hue_neg = -0.763932

        graphics = []
        for indx, line in enumerate(all_points):
            graphics.append(Expression('Hue', hue, 0.6, 0.6))
            for segment in line:
                if joined:
                    graphics.append(Expression('Line', from_python(segment)))
                    if filling is not None:
                        graphics.append(Expression('Hue', hue, 0.6, 0.6, 0.2))
                        fill_area = list(segment)
                        fill_area.append([segment[-1][0], filling])
                        fill_area.append([segment[0][0], filling])
                        graphics.append(Expression(
                            'Polygon', from_python(fill_area)))
                else:
                    graphics.append(Expression('Point', from_python(segment)))
                    if filling is not None:
                        for point in segment:
                            graphics.append(Expression(
                                'Line', from_python([[point[0], filling],
                                                    [point[0], point[1]]])))

            if indx % 4 == 0:
                hue += hue_pos
            else:
                hue += hue_neg
            if hue > 1:
                hue -= 1
            if hue < 0:
                hue += 1

        options['PlotRange'] = from_python([x_range, y_range])

        return Expression('Graphics', Expression('List', *graphics),
                          *options_to_rules(options))
Exemple #17
0
    def apply(self, points, evaluation, options):
        "%(name)s[points_, OptionsPattern[%(name)s]]"

        plot_name = self.get_name()
        all_points = points.to_python(n_evaluation=evaluation)
        expr = Expression(self.get_name(), points, *options_to_rules(options))

        # PlotRange Option
        def check_range(range):
            if range in ("Automatic", "All"):
                return True
            if isinstance(range, list) and len(range) == 2:
                if isinstance(range[0], numbers.Real) and isinstance(range[1], numbers.Real):
                    return True
            return False

        plotrange_option = self.get_option(options, "PlotRange", evaluation)
        plotrange = plotrange_option.to_python(n_evaluation=evaluation)
        if plotrange == "All":
            plotrange = ["All", "All"]
        elif plotrange == "Automatic":
            plotrange = ["Automatic", "Automatic"]
        elif isinstance(plotrange, numbers.Real):
            plotrange = [[-plotrange, plotrange], [-plotrange, plotrange]]
        elif isinstance(plotrange, list) and len(plotrange) == 2:
            if all(isinstance(pr, numbers.Real) for pr in plotrange):
                plotrange = ["All", plotrange]
            elif all(check_range(pr) for pr in plotrange):
                pass
        else:
            evaluation.message(self.get_name(), "prng", plotrange_option)
            plotrange = ["Automatic", "Automatic"]

        x_range, y_range = plotrange[0], plotrange[1]
        assert x_range in ("Automatic", "All") or isinstance(x_range, list)
        assert y_range in ("Automatic", "All") or isinstance(y_range, list)

        # Filling option
        # TODO: Fill between corresponding points in two datasets:
        filling_option = self.get_option(options, "Filling", evaluation)
        filling = filling_option.to_python(n_evaluation=evaluation)
        if filling in ["Top", "Bottom", "Axis"] or isinstance(filling, numbers.Real):
            pass
        else:
            filling = None  # Mathematica does not even check that filling is sane

        # Joined Option
        joined_option = self.get_option(options, "Joined", evaluation)
        joined = joined_option.to_python()
        if joined not in [True, False]:
            evaluation.message(plot_name, "joind", joined_option, expr)
            joined = False

        if isinstance(all_points, list) and len(all_points) != 0:
            if all(not isinstance(point, list) for point in all_points):  # Only y values given
                all_points = [[[float(i), all_points[i]] for i in range(len(all_points))]]
            elif all(isinstance(line, list) and len(line) == 2 for line in all_points):  # Single list of (x,y) pairs
                all_points = [all_points]
            elif all(isinstance(line, list) for line in all_points):  # List of lines
                if all(isinstance(point, list) and len(point) == 2 for line in all_points for point in line):
                    pass
                elif all(not isinstance(point, list) for line in all_points for point in line):
                    all_points = [[[float(i), line[i]] for i in range(len(line))] for line in all_points]
                else:
                    return
            else:
                return
        else:
            return

        y_range = get_plot_range(
            [y for line in all_points for x, y in line], [y for line in all_points for x, y in line], y_range
        )
        x_range = get_plot_range(
            [x for line in all_points for x, y in line], [x for line in all_points for x, y in line], x_range
        )

        if filling == "Axis":
            # TODO: Handle arbitary axis intercepts
            filling = 0.0
        elif filling == "Bottom":
            filling = y_range[0]
        elif filling == "Top":
            filling = y_range[1]

        hue = 0.67
        hue_pos = 0.236068
        hue_neg = -0.763932

        graphics = []
        for indx, line in enumerate(all_points):
            graphics.append(Expression("Hue", hue, 0.6, 0.6))
            if joined:
                graphics.append(Expression("Line", from_python(line)))
                if filling is not None:
                    graphics.append(Expression("Hue", hue, 0.6, 0.6, 0.2))
                    fill_area = list(line)
                    fill_area.append([x_range[1], filling])
                    fill_area.append([x_range[0], filling])
                    graphics.append(Expression("Polygon", from_python(fill_area)))
            else:
                graphics.append(Expression("Point", from_python(line)))
                if filling is not None:
                    for point in line:
                        graphics.append(Expression("Line", from_python([[point[0], filling], [point[0], point[1]]])))

            if indx % 4 == 0:
                hue += hue_pos
            else:
                hue += hue_neg
            if hue > 1:
                hue -= 1
            if hue < 0:
                hue += 1

        options["PlotRange"] = from_python([x_range, y_range])

        return Expression("Graphics", Expression("List", *graphics), *options_to_rules(options))
Exemple #18
0
    def apply(self, functions, x, start, stop, evaluation, options):
        'Plot[functions_, {x_Symbol, start_, stop_}, OptionsPattern[Plot]]'

        expr = Expression('Plot', functions,
                          Expression('List', x, start, stop),
                          *options_to_rules(options))
        if functions.has_form('List', None):
            functions = functions.leaves
        else:
            functions = [functions]
        x = x.get_name()
        try:
            start = start.to_number(n_evaluation=evaluation)
        except NumberError:
            evaluation.message('Plot', 'plln', start, expr)
            return
        try:
            stop = stop.to_number(n_evaluation=evaluation)
        except NumberError:
            evaluation.message('Plot', 'plln', stop, expr)
            return

        def eval_f(f, x_value):
            value = dynamic_scoping(f.evaluate, {x: x_value}, evaluation)
            value = chop(value).get_real_value()
            return value

        hue = 0.67
        hue_pos = 0.236068
        hue_neg = -0.763932

        graphics = []
        for index, f in enumerate(functions):
            points = []
            continuous = False
            steps = 50
            d = (stop - start) / steps
            for index in range(steps + 1):
                x_value = start + index * d
                y = eval_f(f, Real(x_value))
                if y is not None:
                    point = (x_value, y)
                    if continuous:
                        points[-1].append(point)
                    else:
                        points.append([point])
                    continuous = True
                else:
                    continuous = False
            graphics.append(Expression('Hue', hue, 0.6, 0.6))
            graphics.append(
                Expression(
                    'Line',
                    Expression(
                        'List',
                        *(Expression(
                            'List',
                            *(Expression('List', Real(x), Real(y))
                              for x, y in line)) for line in points))))

            if index % 4 == 0:
                hue += hue_pos
            else:
                hue += hue_neg
            if hue > 1: hue -= 1
            if hue < 0: hue += 1

        return Expression('Graphics', Expression('List', *graphics),
                          *options_to_rules(options))
Exemple #19
0
class DensityPlot(Builtin):
    """
    <dl>
    <dt>'DensityPlot[$f$, {$x$, $xmin$, $xmax$}, {$y$, $ymin$, $ymax$}]'
        <dd>plots a density plot of $f$ with $x$ ranging from $xmin$ to $xmax$ and $y$ ranging from $ymin$ to $ymax$.
    </dl>
    
    >> DensityPlot[x ^ 2 + 1 / y, {x, -1, 1}, {y, 1, 4}]
     = -Graphics-
    """

    from graphics import Graphics

    attributes = ('HoldAll', )

    options = Graphics.options.copy()
    options.update({
        'Axes': 'False',
        'AspectRatio': '1',
        'Frame': 'True',
        'ColorFunction': 'Automatic',
        'ColorFunctionScaling': 'True',
    })

    def apply(self, f, x, xstart, xstop, y, ystart, ystop, evaluation,
              options):
        'DensityPlot[f_, {x_Symbol, xstart_, xstop_}, {y_Symbol, ystart_, ystop_}, OptionsPattern[DensityPlot]]'

        x = x.get_name()
        y = y.get_name()

        color_function = self.get_option(options,
                                         'ColorFunction',
                                         evaluation,
                                         pop=True)
        color_function_scaling = self.get_option(options,
                                                 'ColorFunctionScaling',
                                                 evaluation,
                                                 pop=True)

        color_function_min = color_function_max = None
        if color_function.get_name() == 'Automatic':
            color_function = String('LakeColors')
        if color_function.get_string_value():
            func = Expression(
                'ColorData',
                color_function.get_string_value()).evaluate(evaluation)
            if func.has_form('ColorDataFunction', 4):
                color_function_min = func.leaves[2].leaves[0].get_real_value()
                color_function_max = func.leaves[2].leaves[1].get_real_value()
                color_function = Expression(
                    'Function',
                    Expression(func.leaves[3], Expression('Slot', 1)))
            else:
                evaluation.message('DensityPlot', 'color', func)
                return
        if color_function.has_form('ColorDataFunction', 4):
            color_function_min = color_function.leaves[2].leaves[
                0].get_real_value()
            color_function_max = color_function.leaves[2].leaves[
                1].get_real_value()

        color_function_scaling = color_function_scaling.is_true()

        try:
            xstart, xstop, ystart, ystop = [
                value.to_number(n_evaluation=evaluation)
                for value in (xstart, xstop, ystart, ystop)
            ]
        except NumberError, exc:
            expr = Expression('DensityPlot', f,
                              Expression('List', x, xstart, xstop),
                              Expression('List', y, ystart, ystop),
                              *options_to_rules(options))
            evaluation.message('DensityPlot', 'plln', exc.value, expr)
            return

        #print "Initialized"

        stored = {}

        def eval_f(x_value, y_value):
            value = stored.get((x_value, y_value), False)
            if value == False:
                value = dynamic_scoping(f.evaluate, {
                    x: Real(x_value),
                    y: Real(y_value)
                }, evaluation)
                value = chop(value).get_real_value()
                value = float(value)
                stored[(x_value, y_value)] = value
            return value

        v_borders = [None, None]

        triangles = []

        eps = 0.01

        def triangle(x1, y1, x2, y2, x3, y3, depth=None):
            if depth is None:
                x1, x2, x3 = [
                    xstart + value * (xstop - xstart) for value in (x1, x2, x3)
                ]
                y1, y2, y3 = [
                    ystart + value * (ystop - ystart) for value in (y1, y2, y3)
                ]
                depth = 0
            v1, v2, v3 = eval_f(x1, y1), eval_f(x2, y2), eval_f(x3, y3)
            for v in (v1, v2, v3):
                if v_borders[0] is None or v < v_borders[0]:
                    v_borders[0] = v
                if v_borders[1] is None or v > v_borders[1]:
                    v_borders[1] = v
            if v1 is None or v2 is None or v3 is None:
                return
            limit = (v_borders[1] - v_borders[0]) * eps
            if depth < 2:
                if abs(v1 - v2) > limit:
                    triangle(x1, y1, x3, y3, (x1 + x2) / 2, (y1 + y2) / 2,
                             depth + 1)
                    triangle(x2, y2, x3, y3, (x1 + x2) / 2, (y1 + y2) / 2,
                             depth + 1)
                    return
                if abs(v2 - v3) > limit:
                    triangle(x1, y1, x2, y2, (x2 + x3) / 2, (y2 + y3) / 2,
                             depth + 1)
                    triangle(x1, y1, x3, y3, (x2 + x3) / 2, (y2 + y3) / 2,
                             depth + 1)
                    return
                if abs(v1 - v3) > limit:
                    triangle(x2, y2, x1, y1, (x1 + x3) / 2, (y1 + y3) / 2,
                             depth + 1)
                    triangle(x2, y2, x3, y3, (x1 + x3) / 2, (y1 + y3) / 2,
                             depth + 1)
                    return
            triangles.append([(x1, y1, v1), (x2, y2, v2), (x3, y3, v3)])

        points = 7
        num = points * 1.0
        for xi in range(points):
            for yi in range(points):
                triangle(xi / num, yi / num, (xi + 1) / num, (yi + 1) / num,
                         (xi + 1) / num, yi / num)
                triangle(xi / num, yi / num, (xi + 1) / num, (yi + 1) / num,
                         xi / num, (yi + 1) / num)

        v_min = v_max = None

        #if color_function_scaling:
        for t in triangles:
            for tx, ty, v in t:
                if v_min is None or v < v_min:
                    v_min = v
                if v_max is None or v > v_max:
                    v_max = v
        v_range = v_max - v_min
        if v_range == 0:
            v_range = 1

        if color_function.has_form('ColorDataFunction', 4):
            color_func = color_function.leaves[3]
        else:
            color_func = color_function
        if color_function_scaling and color_function_min is not None and color_function_max is not None:
            color_function_range = color_function_max - color_function_min

        colors = {}

        def eval_color(x, y, v):
            #v_lookup = int(v * 100)
            #if color_function_scaling:
            v_scaled = (v - v_min) / v_range
            if color_function_scaling and color_function_min is not None and color_function_max is not None:
                v_color_scaled = color_function_min + v_scaled * color_function_range
            else:
                v_color_scaled = v
            v_lookup = int(
                v_scaled * 100 +
                0.5)  # calculate and store 100 different shades max.
            value = colors.get(v_lookup)
            if value is None:
                #print "Calc"
                #print "Scale"
                #print "Expression"
                #print "Calc color for %f" % v_scaled
                value = Expression(color_func, Real(v_color_scaled))
                #print "Evaluate %s" % value
                value = value.evaluate(evaluation)
                #value = Expression('RGBColor', Real(0.5), Real(0.5), Real(0.5))
                #print "Set"
                colors[v_lookup] = value
            return value

        #print "Points"
        points = []
        vertex_colors = []
        for p1, p2, p3 in triangles:
            #print "Triangle %s,%s,%s" % (p1, p2, p3)
            c1, c2, c3 = eval_color(*p1), eval_color(*p2), eval_color(*p3)
            #print "Append"
            points.append(
                Expression('List', Expression('List', *p1[:2]),
                           Expression('List', *p2[:2]),
                           Expression('List', *p3[:2])))
            vertex_colors.append(Expression('List', c1, c2, c3))

        #print "Polygon"
        polygon = Expression(
            'Polygon', Expression('List', *points),
            Expression('Rule', Symbol('VertexColors'),
                       Expression('List', *vertex_colors)))
        #print "Result"
        result = Expression('Graphics', polygon, *options_to_rules(options))
        #print "Return"
        return result
Exemple #20
0
    def apply(self, functions, x, xstart, xstop, y, ystart, ystop, evaluation,
              options):
        '''%(name)s[functions_, {x_Symbol, xstart_, xstop_},
                {y_Symbol, ystart_, ystop_}, OptionsPattern[%(name)s]]'''
        xexpr_limits = Expression('List', x, xstart, xstop)
        yexpr_limits = Expression('List', y, ystart, ystop)
        expr = Expression(self.get_name(), functions, xexpr_limits,
                          yexpr_limits, *options_to_rules(options))

        functions = self.get_functions_param(functions)
        plot_name = self.get_name()

        try:
            xstart, xstop, ystart, ystop = \
                [value.to_number(n_evaluation=evaluation)
                 for value in (xstart, xstop, ystart, ystop)]

        except NumberError:
            expr = Expression(
                plot_name, functions, Expression('List', x, xstart, xstop),
                Expression('List', y, ystart, ystop),
                *options_to_rules(options))
            evaluation.message(plot_name, 'plln', value, expr)
            return

        if ystart >= ystop:
            evaluation.message(plot_name, 'plln', ystop, expr)
            return

        if xstart >= xstop:
            evaluation.message(plot_name, 'plln', xstop, expr)
            return

        # Mesh Option
        mesh_option = self.get_option(options, 'Mesh', evaluation)
        mesh = mesh_option.to_python()
        if mesh not in ['None', 'Full', 'All']:
            evaluation.message('Mesh', 'ilevels', mesh_option)
            mesh = 'Full'

        # PlotPoints Option
        plotpoints_option = self.get_option(options, 'PlotPoints', evaluation)
        plotpoints = plotpoints_option.to_python()

        def check_plotpoints(steps):
            if isinstance(steps, int) and steps > 0:
                return True
            return False

        if plotpoints == 'None':
            plotpoints = [7, 7]
        elif check_plotpoints(plotpoints):
            plotpoints = [plotpoints, plotpoints]

        if not (isinstance(plotpoints, list) and len(plotpoints) == 2 and
                check_plotpoints(plotpoints[0]) and
                check_plotpoints(plotpoints[1])):
            evaluation.message(self.get_name(), 'invpltpts', plotpoints)
            plotpoints = [7, 7]

        graphics = []
        for indx, f in enumerate(functions):
            stored = {}

            def eval_f(x_value, y_value):
                value = stored.get((x_value, y_value), False)
                if value is False:
                    value = quiet_evaluate(f, {x: Real(
                        x_value), y: Real(y_value)}, evaluation)
                    # value = dynamic_scoping(
                    #    f.evaluate, {x: Real(x_value), y: Real(y_value)},
                    #    evaluation)
                    # value = chop(value).get_real_value()
                    if value is not None:
                        value = float(value)
                    stored[(x_value, y_value)] = value
                return value

            v_borders = [None, None]

            triangles = []

            eps = 0.01

            def triangle(x1, y1, x2, y2, x3, y3, depth=None):
                if depth is None:
                    x1, x2, x3 = [xstart + value * (xstop - xstart)
                                  for value in (x1, x2, x3)]
                    y1, y2, y3 = [ystart + value * (ystop - ystart)
                                  for value in (y1, y2, y3)]
                    depth = 0
                v1, v2, v3 = eval_f(x1, y1), eval_f(x2, y2), eval_f(x3, y3)
                for v in (v1, v2, v3):
                    if v is not None:
                        if v_borders[0] is None or v < v_borders[0]:
                            v_borders[0] = v
                        if v_borders[1] is None or v > v_borders[1]:
                            v_borders[1] = v
                if v1 is None or v2 is None or v3 is None:
                    if depth < 2:
                        triangle(x1, y1, (x1 + x2) / 2, (y1 + y2) / 2,
                                 (x1 + x3) / 2, (y1 + y3) / 2, depth + 1)
                        triangle(x2, y2, (x1 + x2) / 2, (y1 + y2) / 2,
                                 (x2 + x3) / 2, (y2 + y3) / 2, depth + 1)
                        triangle(x3, y3, (x1 + x3) / 2, (y1 + y3) / 2,
                                 (x2 + x3) / 2, (y2 + y3) / 2, depth + 1)
                        triangle((x1 + x2) / 2, (y1 + y2) / 2, (x2 + x3) / 2,
                                 (y2 + y3) / 2, (x1 + x3) / 2, (y1 + y3) / 2,
                                 depth + 1)
                    return
                limit = (v_borders[1] - v_borders[0]) * eps
                if depth < 2:
                    if abs(v1 - v2) > limit:
                        triangle(x1, y1, x3, y3, (x1 + x2) / 2, (y1 + y2) / 2,
                                 depth + 1)
                        triangle(x2, y2, x3, y3, (x1 + x2) / 2, (y1 + y2) / 2,
                                 depth + 1)
                        return
                    if abs(v2 - v3) > limit:
                        triangle(x1, y1, x2, y2, (
                            x2 + x3) / 2, (y2 + y3) / 2, depth + 1)
                        triangle(x1, y1, x3, y3, (
                            x2 + x3) / 2, (y2 + y3) / 2, depth + 1)
                        return
                    if abs(v1 - v3) > limit:
                        triangle(x2, y2, x1, y1, (
                            x1 + x3) / 2, (y1 + y3) / 2, depth + 1)
                        triangle(x2, y2, x3, y3, (
                            x1 + x3) / 2, (y1 + y3) / 2, depth + 1)
                        return
                triangles.append([(x1, y1, v1), (x2, y2, v2), (x3, y3, v3)])

            numx = plotpoints[0] * 1.0
            numy = plotpoints[1] * 1.0
            for xi in range(plotpoints[0]):
                for yi in range(plotpoints[1]):
                    triangle(xi / numx, yi / numy, (xi + 1) / numx,
                             (yi + 1) / numy, (xi + 1) / numx, yi / numy)
                    triangle(xi / numx, yi / numy, (xi + 1) / numx,
                             (yi + 1) / numy, xi / numx, (yi + 1) / numy)

            # Mesh should just be looking up stored values
            mesh_points = []
            for xi in range(plotpoints[0] + 1):
                xval = xstart + xi / numx * (xstop - xstart)
                mesh_row = []
                for yi in range(plotpoints[1] + 1):
                    yval = ystart + yi / numy * (ystop - ystart)
                    z = eval_f(xval, yval)
                    if z is not None:
                        mesh_row.append((xval, yval, z))
                mesh_points.append(mesh_row)

            for yi in range(plotpoints[1] + 1):
                yval = ystart + yi / numy * (ystop - ystart)
                mesh_col = []
                for xi in range(plotpoints[0] + 1):
                    xval = xstart + xi / numx * (xstop - xstart)
                    z = eval_f(xval, yval)
                    if z is not None:
                        mesh_col.append((xval, yval, z))
                mesh_points.append(mesh_col)

            # Fix the grid near recursions
            x_grids = [xstart + (xi / numx) * (xstop - xstart)
                       for xi in range(plotpoints[0] + 1)]
            y_grids = [ystart + (yi / numy) * (ystop - ystart)
                       for yi in range(plotpoints[1] + 1)]

            for (xval, yval) in stored.keys():
                if xval in x_grids:
                    x_index = int((xval - xstart) * numx / (xstop - xstart) +
                                  0.5)
                    z = eval_f(xval, yval)
                    if z is not None:
                        mesh_points[x_index].append((xval, yval, z))
                if yval in y_grids:
                    y_index = int((yval - ystart) * numy / (ystop - ystart) +
                                  plotpoints[0] + 1.5)
                    z = eval_f(xval, yval)
                    if z is not None:
                        mesh_points[y_index].append((xval, yval, z))

            for mesh_line in mesh_points:
                mesh_line.sort()

            v_min = v_max = None

            for t in triangles:
                for tx, ty, v in t:
                    if v_min is None or v < v_min:
                        v_min = v
                    if v_max is None or v > v_max:
                        v_max = v
            graphics.extend(self.construct_graphics(
                triangles, mesh_points, v_min, v_max, options, evaluation))
        return self.final_graphics(graphics, options)
Exemple #21
0
 def final_graphics(self, graphics, options):
     return Expression("Graphics", Expression("List", *graphics), *options_to_rules(options))