Esempio n. 1
0
    def _setup(self, layers, layer_idx):
        basemap = layers[0]

        self.color = self.color or DEFAULT_COLORS[layer_idx]
        self.cartocss = self._get_cartocss(basemap)

        if self.time:
            column = self.time['column']
            frames = self.time['frames']
            method = self.time['method']
            duration = self.time['duration']
            agg_func = "'{method}({time_column})'".format(method=method,
                                                          time_column=column)
            self.torque_cartocss = cssify({
                'Map': {
                    '-torque-frame-count':
                    frames,
                    '-torque-animation-duration':
                    duration,
                    '-torque-time-attribute':
                    "'{}'".format(column),
                    '-torque-aggregation-function':
                    agg_func,
                    '-torque-resolution':
                    1,
                    '-torque-data-aggregation':
                    ('cumulative' if self.time['cumulative'] else 'linear'),
                },
            })
            self.cartocss += self.torque_cartocss
Esempio n. 2
0
    def test_cssify(self):
        """utils.cssify"""
        # point style
        point_stylecss = cssify(self.point_style)
        self.assertEqual(point_stylecss,
                         ("#layer['mapnik::geometry_type'=1] {  "
                          "marker-width: 6; marker-fill: yellow; "
                          "marker-fill-opacity: 1; marker-allow-overlap: "
                          "true; marker-line-width: 0.5; marker-line-color: "
                          "black; marker-line-opacity: 1;} "),
                         msg="point style")

        # polygon style
        polygon_stylecss = cssify(self.polygon_style)
        self.assertEqual(polygon_stylecss,
                         ("#layer['mapnik::geometry_type'=3] {  "
                          "polygon-fill: ramp([column], (#ffc6c4, #ee919b, "
                          "#cc607d, #9e3963, #672044), quantiles); "
                          "polygon-opacity: 0.9; polygon-gamma: 0.5; "
                          "line-color: #FFF; line-width: 0.5; line-opacity: "
                          "0.25; line-comp-op: hard-light;} "),
                         msg="polygon style")

        # complex style
        complex_stylecss = cssify(self.complex_style)
        self.assertEqual(complex_stylecss,
                         ("#layer['mapnik::geometry_type'=1] {  "
                          "marker-width: 5; marker-fill: yellow; "
                          "marker-fill-opacity: 1; marker-allow-overlap: "
                          "true; marker-line-width: 0.5; marker-line-color: "
                          "black; marker-line-opacity: 1;} "
                          "#layer['mapnik::geometry_type'=2] {  "
                          "line-width: 1.5; line-color: black;} "
                          "#layer['mapnik::geometry_type'=3] {  "
                          "polygon-fill: blue; polygon-opacity: 0.9; "
                          "polygon-gamma: 0.5; line-color: #FFF; line-width: "
                          "0.5; line-opacity: 0.25; "
                          "line-comp-op: hard-light;} "),
                         msg="multi-layer styling")
Esempio n. 3
0
    def _get_cartocss(self, basemap):
        """Generate cartocss for class properties"""
        if isinstance(self.size, int):
            size_style = self.size
        elif isinstance(self.size, dict):
            size_style = ('ramp([{column}],'
                          ' range({min_range},{max_range}),'
                          ' {bin_method}({bins}))').format(
                              column=self.size['column'],
                              min_range=self.size['range'][0],
                              max_range=self.size['range'][1],
                              bin_method=self.size['bin_method'],
                              bins=self.size['bins'])

        if self.scheme:
            color_style = get_scheme_cartocss(self.color, self.scheme)
        else:
            color_style = self.color

        line_color = '#000' if basemap.source == 'dark' else '#FFF'
        return cssify({
            # Point CSS
            "#layer['mapnik::geometry_type'=1]": {
                'marker-width': size_style,
                'marker-fill': color_style,
                'marker-fill-opacity': '1',
                'marker-allow-overlap': 'true',
                'marker-line-width': '0.5',
                'marker-line-color': line_color,
                'marker-line-opacity': '1',
            },
            # Line CSS
            "#layer['mapnik::geometry_type'=2]": {
                'line-width': '1.5',
                'line-color': color_style,
            },
            # Polygon CSS
            "#layer['mapnik::geometry_type'=3]": {
                'polygon-fill': color_style,
                'polygon-opacity': '0.9',
                'polygon-gamma': '0.5',
                'line-color': '#FFF',
                'line-width': '0.5',
                'line-opacity': '0.25',
                'line-comp-op': 'hard-light',
            }
        })
Esempio n. 4
0
    def _get_cartocss(self, basemap, has_time=False):
        """Generate cartocss for class properties"""
        if isinstance(self.size, int):
            size_style = self.size or 4
        elif isinstance(self.size, dict):
            size_style = ('ramp([{column}],'
                          ' range({min_range},{max_range}),'
                          ' {bin_method}({bins}))').format(
                              column=self.size['column'],
                              min_range=self.size['range'][0],
                              max_range=self.size['range'][1],
                              bin_method=self.size['bin_method'],
                              bins=self.size['bins'])

        if self.scheme:
            color_style = get_scheme_cartocss(
                'value' if has_time else self.color,
                self.scheme)
        else:
            color_style = self.color

        line_color = '#000' if basemap.source == 'dark' else '#FFF'
        if self.time:
            css = cssify({
                # Torque Point CSS
                "#layer": {
                    'marker-width': size_style,
                    'marker-fill': color_style,
                    'marker-fill-opacity': 0.9,
                    'marker-allow-overlap': 'true',
                    'marker-line-width': 0,
                    'marker-line-color': line_color,
                    'marker-line-opacity': 1,
                    'comp-op': 'source-over',
                }
            })
            if self.color in self.style_cols:
                css += cssify({
                    '#layer[{} = null]'.format(self.color): {
                        'marker-fill': '#666'}
                    })
            for trail_num in range(1, self.time['trails'] + 1):
                # Trails decay as 1/2^n, and grow 30% at each step
                trail_temp = cssify({
                    '#layer[frame-offset={}]'.format(trail_num): {
                        'marker-width': size_style * (1.0 + trail_num * 0.3),
                        'marker-opacity': 0.9 / 2.0**trail_num,
                    }
                })
                css += trail_temp
            return css
        else:
            if self.geom_type == 'point':
                css = cssify({
                    # Point CSS
                    "#layer": {
                        'marker-width': size_style,
                        'marker-fill': color_style,
                        'marker-fill-opacity': '1',
                        'marker-allow-overlap': 'true',
                        'marker-line-width': '0.5',
                        'marker-line-color': line_color,
                        'marker-line-opacity': '1',
                    }})
                if self.color in self.style_cols:
                    css += cssify({
                        '#layer[{} = null]'.format(self.color): {
                            'marker-fill': '#ccc'}
                        })
                return css
            elif self.geom_type == 'line':
                css = cssify({
                    "#layer": {
                        'line-width': '1.5',
                        'line-color': color_style,
                    }})
                if self.color in self.style_cols:
                    css += cssify({
                        '#layer[{} = null]'.format(self.color): {
                            'line-color': '#ccc'}
                        })
                return css
            elif self.geom_type == 'polygon':
                css = cssify({
                    "#layer": {
                        'polygon-fill': color_style,
                        'polygon-opacity': '0.9',
                        'polygon-gamma': '0.5',
                        'line-color': '#FFF',
                        'line-width': '0.5',
                        'line-opacity': '0.25',
                        'line-comp-op': 'hard-light',
                    }})
                if self.color in self.style_cols:
                    css += cssify({
                        '#layer[{} = null]'.format(self.color): {
                            'polygon-fill': '#ccc'}
                        })
                return css
            else:
                raise ValueError('Unsupported geometry type: {}'.format(
                    self.geom_type))
Esempio n. 5
0
    def _setup(self, layers, layer_idx):
        basemap = layers[0]

        # if color not specified, choose a default
        # choose color time default
        if self.time:
            # default torque color
            self.color = self.color or '#2752ff'
        else:
            self.color = self.color or DEFAULT_COLORS[layer_idx]
        # choose appropriate scheme if not already specified
        if (not self.scheme) and (self.color in self.style_cols):
            if self.style_cols[self.color] in ('string', 'boolean', ):
                self.scheme = antique(10)
            elif self.style_cols[self.color] in ('number', ):
                self.scheme = mint(5)
            elif self.style_cols[self.color] in ('date', 'geometry', ):
                raise ValueError(
                    'Cannot style column `{col}` of type `{type}`. It must be '
                    'numeric, text, or boolean.'.format(
                        col=self.color, type=self.style_cols[self.color]))

        if self.time:
            # validate time column information
            if self.geom_type != 'point':
                raise ValueError('Cannot do time-based maps with data in '
                                 '`{query}` since this table does not contain '
                                 'point geometries'.format(
                                     query=self.orig_query))
            elif self.style_cols[self.time['column']] not in (
                    'number', 'date', ):
                raise ValueError('Cannot create an animated map from column '
                                 '`{col}` because it is of type {t1}. It must '
                                 'be of type number or date.'.format(
                                     col=self.time['column'],
                                     t1=self.style_cols[self.time['column']]))

            # don't use turbo-carto for animated maps
            column = self.time['column']
            frames = self.time['frames']
            method = self.time['method']
            duration = self.time['duration']
            if (self.color in self.style_cols and
                    self.style_cols[self.color] in ('string', 'boolean', )):
                self.query = minify_sql([
                    'SELECT',
                    '    orig.*, __wrap.cf_value_{col}',
                    'FROM ({query}) AS orig, (',
                    '    SELECT',
                    '      row_number() OVER (',
                    '        ORDER BY val_{col}_cnt DESC) AS cf_value_{col},',
                    '      {col}',
                    '    FROM (',
                    '        SELECT {col}, count({col}) AS val_{col}_cnt',
                    '        FROM ({query}) as orig',
                    '        GROUP BY {col}',
                    '        ORDER BY 2 DESC',
                    '    ) AS _wrap',
                    ') AS __wrap',
                    'WHERE __wrap.{col} = orig.{col}',
                ]).format(col=self.color, query=self.orig_query)
                agg_func = '\'CDB_Math_Mode(cf_value_{})\''.format(self.color)
                self.scheme = {
                    'bins': [str(i) for i in range(1, 11)],
                    'name': (self.scheme.get('name') if self.scheme
                             else 'Bold'),
                    'bin_method': '', }
            elif (self.color in self.style_cols and
                  self.style_cols[self.color] in ('number', )):
                self.query = ' '.join([
                    'SELECT *, {col} as value',
                    'FROM ({query}) as _wrap'
                ]).format(col=self.color, query=self.orig_query)
                agg_func = '\'avg({})\''.format(self.color)
            else:
                agg_func = "'{method}(cartodb_id)'".format(
                    method=method)
            self.torque_cartocss = cssify({
                'Map': {
                    '-torque-frame-count': frames,
                    '-torque-animation-duration': duration,
                    '-torque-time-attribute': "'{}'".format(column),
                    '-torque-aggregation-function': agg_func,
                    '-torque-resolution': 1,
                    '-torque-data-aggregation': ('cumulative'
                                                 if self.time['cumulative']
                                                 else 'linear'),
                },
            })
            self.cartocss = (self.torque_cartocss
                             + self._get_cartocss(basemap, has_time=True))
        else:
            # use turbo-carto for non-animated maps
            self.cartocss = self._get_cartocss(basemap)