Exemple #1
0
    def set_data(self, dataset, geometry, name, aoi_name):
        """set the dataset and the geometry to allow the download"""

        self.geometry = geometry
        self.dataset = dataset
        self.name = name
        self.aoi_name = aoi_name

        # add vizualization properties to the image
        # cast to image as set is a ee.Element method
        self.dataset = ee.Image(
            dataset.set({
                "visualization_0_bands":
                "constant",
                "visualization_0_max":
                5,
                "visualization_0_min":
                0,
                "visualization_0_name":
                "restauration index",
                "visualization_0_palette":
                ",".join(cp.no_data_color + cp.gradient(5)),
                "visualization_0_type":
                "continuous",
            }))

        return self
Exemple #2
0
    def _apply(self, widget, event, data):
        """download the dataset using the given parameters"""

        folder = Path(ee.data.getAssetRoots()[0]["id"])

        # check if a dataset is existing
        if self.dataset == None or self.geometry == None:
            return self

        # set the parameters
        name = self.name or dt.now().strftime("%Y-%m-%d_%H-%M-%S")
        export_params = {
            "image": self.dataset,
            "description": name,
            "scale": self.w_scale.v_model,
            "region": self.geometry,
            "maxPixels": 1e13,
        }

        # launch the task
        if self.w_method.v_model == "gee":
            export_params.update(assetId=str(folder / name))
            task = ee.batch.Export.image.toAsset(**export_params)
            task.start()
            self.alert.add_msg(
                "the task have been launched in your GEE acount", "success")

        elif self.w_method.v_model == "sepal":

            gdrive = cs.gdrive()

            files = gdrive.get_files(name)
            if files == []:
                task = ee.batch.Export.image.toDrive(**export_params)
                task.start()
                gee.wait_for_completion(name, self.alert)
                files = gdrive.get_files(name)

            # save everything in the same folder as the json file
            # no need to create it it's created when the recipe is saved
            result_dir = cp.result_dir / aoi_name

            tile_list = gdrive.download_files(files, result_dir)
            gdrive.delete_files(files)

            # add the colormap to each tile
            colormap = {}
            for code, color in enumerate(no_data_color + cp.gradient(5)):
                colormap[i] = tuple(int(c * 255) for c in to_rgba(color))

            for tile in tile_list:

                with rio.open(tile) as f:

                    dst_f.write_colormap(self.band, colormap)

            self.alert.add_msg("map exported", "success")

        return self
    def digest_layers(self, layer_io=None, question_io=None):
        """
        Digest the layers as a json list. This list should be composed of at least 6 information : id, name, layer, theme and subtheme
        When digestion, the layout will represent each layer sorted by categories
        fore each one of them if the layer used is the default one we'll write default, if not the name of the layer.
        for each one of them the value of the weight will also be set
        """

        if layer_io == None or question_io == None:
            return self

        # read the json str into a panda dataframe
        layer_list = layer_io.layer_list
        layer_list = pd.DataFrame(layer_list) if layer_list else self.LAYER_LIST

        # get all the themes
        themes = np.unique(layer_list.theme)

        ep_content = []
        for theme in themes:

            # filter the layers
            tmp_layers = layer_list[layer_list.theme == theme]

            # add the theme title
            title = v.ExpansionPanelHeader(children=[theme.capitalize()])

            # loop in these layers and create the widgets
            theme_layer_widgets = []
            for i, row in tmp_layers.iterrows():

                # get the original layer asset
                original_asset = self.LAYER_LIST[self.LAYER_LIST.layer_id == row["id"]][
                    "layer"
                ].values[0]

                # cannot make the slots work with icons so I need to move to intermediate layout
                if row["theme"] == "benefits":

                    # get the weight from questionnaire
                    weight = json.loads(question_io.priorities)[row["id"]]

                    # create the widget
                    theme_layer_widgets.append(
                        v.Row(
                            class_="ml-2 mr-2",
                            children=[
                                v.TextField(
                                    small=True,
                                    hint=row["layer"]
                                    if row["layer"] != original_asset
                                    else "default",
                                    persistent_hint=True,
                                    color=cp.gradient(5)[weight],
                                    readonly=True,
                                    v_model=row["name"],
                                ),
                                v.Icon(
                                    class_="ml-2",
                                    color=cp.gradient(5)[weight],
                                    children=[f"mdi-numeric-{weight}-circle"],
                                ),
                            ],
                        )
                    )

                elif row["theme"] == "costs":
                    active = True
                    theme_layer_widgets.append(
                        v.Row(
                            class_="ml-2 mr-2",
                            children=[
                                v.TextField(
                                    small=True,
                                    hint=row["layer"]
                                    if row["layer"] != original_asset
                                    else "default",
                                    persistent_hint=True,
                                    color=cp.gradient(2)[active],
                                    readonly=True,
                                    v_model=row["name"],
                                ),
                                v.Icon(
                                    class_="ml-2",
                                    color=cp.gradient(2)[active],
                                    children=["mdi-circle-slice-8"],
                                ),
                            ],
                        )
                    )

                elif row["id"] not in [
                    "ecozones",
                    "land_cover",
                    "treecover_with_potential",
                ]:

                    # get the activation from questionnaire_io if constraint
                    active = json.loads(question_io.constraints)[row["name"]] != -1

                    theme_layer_widgets.append(
                        v.Row(
                            class_="ml-2 mr-2",
                            children=[
                                v.TextField(
                                    small=True,
                                    hint=row["layer"]
                                    if row["layer"] != original_asset
                                    else "default",
                                    persistent_hint=True,
                                    color=cp.gradient(2)[active],
                                    readonly=True,
                                    v_model=row["name"],
                                ),
                                v.Icon(
                                    class_="ml-2",
                                    color=cp.gradient(2)[active],
                                    children=["mdi-circle-slice-8"],
                                ),
                            ],
                        )
                    )

            # add the lines to the layout
            content = v.ExpansionPanelContent(children=theme_layer_widgets)

            # create the ep
            ep_content.append(v.ExpansionPanel(children=[title, content]))

        # add the layout element to the global layout
        self.children = ep_content

        return self
Exemple #4
0
class PriorityTable(v.SimpleTable):

    _labels = [
        "no importance",
        "low importance",
        "neutral",
        "important",
        "very important",
    ]

    _colors = cp.gradient(5)

    _BENEFITS = pd.read_csv(cp.layer_list).fillna("")
    _BENEFITS = _BENEFITS[_BENEFITS.theme == "benefits"]

    _DEFAULT_V_MODEL = {layer_id: 0 for layer_id in _BENEFITS.layer_id}

    def __init__(self):

        # construct the checkbox list
        self.checkbox_list = {}
        for layer_id in self._BENEFITS.layer_id:
            line = []
            for i, color in enumerate(self._colors):
                line.append(
                    v.Checkbox(
                        color=color,
                        _metadata={"label": layer_id, "val": i},
                        v_model=i == 0,
                    )
                )
            self.checkbox_list[layer_id] = line

        # construct the rows of the table
        rows = []
        self.btn_list = []
        for i, layer_row in self._BENEFITS.iterrows():
            edit_btn = v.Icon(
                children=["mdi-pencil"], _metadata={"layer": layer_row.layer_id}
            )
            self.btn_list.append(edit_btn)
            row = [v.Html(tag="td", children=[edit_btn])]
            row.append(v.Html(tag="td", children=[layer_row.layer_name]))
            for j in range(len(self._colors)):
                row.append(
                    v.Html(
                        tag="td", children=[self.checkbox_list[layer_row.layer_id][j]]
                    )
                )
            rows.append(v.Html(tag="tr", children=row))

        # create the table
        super().__init__(
            v_model=json.dumps(self._DEFAULT_V_MODEL),
            children=[
                v.Html(
                    tag="thead",
                    children=[
                        v.Html(
                            tag="tr",
                            children=(
                                [v.Html(tag="th", children=["action"])]
                                + [v.Html(tag="th", children=["indicator"])]
                                + [
                                    v.Html(tag="th", children=[label])
                                    for label in self._labels
                                ]
                            ),
                        )
                    ],
                ),
                v.Html(tag="tbody", children=rows),
            ],
        )

        # link the checks with the v_model
        for name in self._BENEFITS.layer_id.tolist():
            for check in self.checkbox_list[name]:
                check.observe(self._on_check_change, "v_model")

        # action on clicks
        for icon in self.btn_list:
            icon.on_event("click", lambda *args: print("toto"))

    def _on_check_change(self, change):

        line = change["owner"]._metadata["label"]

        # if checkbox is unique and change == false recheck
        if change["new"] == False:
            unique = True
            for check in self.checkbox_list[line]:
                if check.v_model == True:
                    unique = False
                    break

            change["owner"].v_model = unique

        else:
            # uncheck all the others in the line
            for check in self.checkbox_list[line]:
                if check != change["owner"]:
                    check.v_model = False

            # change the table model
            tmp = json.loads(self.v_model)
            tmp[line] = change["owner"]._metadata["val"]
            self.v_model = json.dumps(tmp)

        return

    def load_data(self, data):
        """load the data from a questionnaire io"""

        data = json.loads(data)

        # check the appropriate checkboxes
        for k, v in data.items():
            self.checkbox_list[k][v].v_model = True

        return self
class AreaSumUp(v.Layout):

    NAMES = [
        "restoration potential", "surface (MHa)",
        "ratio over total surface (%)"
    ]
    COLORS = cp.gradient(5) + cp.no_data_color
    POTENTIALS = [
        "Very low", "Low", "Medium", "High", "Very High", "Unsuitable land"
    ]

    def __init__(self, title, surfaces=[0] * 6):

        # get the total surface for ratio
        total_surface = sum(surfaces)

        # normalize surfaces
        norm_surfaces = [(s / total_surface) * 100 for s in surfaces]

        # create a matplotlib stack horizontal bar chart
        chart = Output()
        with chart:

            # create the chart
            fig, ax = plt.subplots(figsize=[50, 2], facecolor=((0, 0, 0, 0)))

            # add the axis
            for i, surface in enumerate(norm_surfaces):
                ax.barh(title,
                        surface,
                        left=sum(norm_surfaces[:i]),
                        color=self.COLORS[i])

            # cosmetic tuning
            ax.set_xlim(0, 100)
            ax.set_axis_off()

            plt.show()

        # init the table
        head = [
            v.Html(
                tag="thead",
                children=[
                    v.Html(
                        tag="tr",
                        children=[
                            v.Html(tag="th", children=[name])
                            for name in self.NAMES
                        ],
                    )
                ],
            )
        ]

        self.rows = []
        for clr, ptl, val, norm in zip(self.COLORS, self.POTENTIALS, surfaces,
                                       norm_surfaces):

            row = v.Html(
                tag="tr",
                children=[
                    v.Html(
                        tag="td",
                        children=[ptl],
                        style_=f"color: {clr}",
                    ),
                    v.Html(tag="td", children=[f"{float(val):.1f}"]),
                    v.Html(tag="td", children=[f"{float(norm):.1f}"]),
                ],
            )

            self.rows.append(row)

        body = [v.Html(tag="tbody", children=self.rows)]
        table = v.SimpleTable(small=True, xs12=True, children=head + body)

        # the table should not be displayed by default but as a detail expansion panel
        ep = v.ExpansionPanels(children=[
            v.ExpansionPanel(children=[
                v.ExpansionPanelHeader(children=[cm.dashboard.region.detail]),
                v.ExpansionPanelContent(children=[table]),
            ])
        ])

        # init the title
        title = v.Html(xs12=True, class_="mb-2", tag="h2", children=[title])

        # create the widget
        super().__init__(
            row=True,
            class_="ma-5",
            children=[
                v.Flex(xs12=True, children=[title]),
                v.Flex(xs12=True, children=[chart]),
                v.Flex(xs12=True, children=[ep]),
            ],
        )
class LayerFull(sw.Layout):

    COLORS = cp.gradient(5) + ["grey"]

    def __init__(self, layer_name, values, aoi_names, colors):

        # read the layer list and find the layer information based on the layer name
        layer_list = pd.read_csv(cp.layer_list).fillna("")
        layer_row = layer_list[layer_list.layer_name == layer_name]

        if len(layer_row) != 1:
            raise IndexError(
                f"The layer {layer_name} is not part of the existing layers of the application. Please contact our maintainer."
            )

        # build the internal details
        details = sw.ExpansionPanels(
            xs12=True,
            class_="mt-3",
            children=[
                sw.ExpansionPanel(children=[
                    sw.ExpansionPanelHeader(
                        children=["Details"],
                        expand_icon="mdi-help-circle-outline",
                        disable_icon_rotate=True,
                    ),
                    sw.ExpansionPanelContent(
                        children=[layer_row.layer_info.values[0]]),
                ])
            ],
        )

        # create a title with the layer name
        title = sw.Html(
            class_="mt-2 mb-2",
            xs12=True,
            tag="h3",
            children=[f"{layer_name} ({layer_row.unit.values[0]})"],
        )

        # taken from https://stackoverflow.com/questions/579310/formatting-long-numbers-as-strings-in-python
        def human_format(num, round_to=2):
            magnitude = 0
            while abs(num) >= 1000:
                magnitude += 1
                num = round(num / 1000.0, round_to)
            return "{:.{}f}{}".format(round(num, round_to), round_to,
                                      ["", "k", "M", "G", "T", "P"][magnitude])

        # create a matplotlib stack horizontal bar chart
        chart = Output()
        with chart:

            # change pyplot style
            plt.style.use("dark_background")

            # create the chart
            fig, ax = plt.subplots(figsize=[50, len(values) * 2],
                                   facecolor=((0, 0, 0, 0)))

            # set the datas
            max_value = max(values)
            norm_values = [v / max_value * 100 for v in reversed(values)]
            human_values = [f"{human_format(val)}" for val in reversed(values)]
            colors = [
                colors[i - 1] if i else scolor.primary
                for i in range(len(values))
            ][::-1]

            # add the axes
            ax.barh(aoi_names, norm_values, color=colors)

            # add the text
            for i, (norm, name, val, color) in enumerate(
                    zip(norm_values, aoi_names, human_values, colors)):
                ax.text(norm + 1, i, val, fontsize=40, color=color)

            # cosmetic tuning
            ax.set_xlim(0, 110)
            ax.tick_params(axis="y",
                           which="major",
                           pad=30,
                           labelsize=40,
                           left=False)
            ax.tick_params(axis="x", bottom=False, labelbottom=False)
            ax.set_frame_on(False)

            plt.show()

        super().__init__(
            class_="ma-5",
            row=True,
            children=[
                sw.Flex(xs12=True, children=[title]),
                sw.Flex(xs12=True, children=[chart]),
                sw.Flex(xs12=True, children=[details]),
            ],
        )