def _init_layout(self):
        """Initialize widget layout."""

        # Control area
        info_box = gui.widgetBox(self.controlArea, "Info", addSpace=True)
        self._info_label = gui.widgetLabel(info_box, "Initializing\n\n")

        indicator_filter_box = gui.widgetBox(self.controlArea,
                                             "Indicators",
                                             addSpace=True)
        gui.radioButtonsInBox(indicator_filter_box,
                              self,
                              "indicator_list_selection",
                              self.indicator_list_map.values(),
                              "Rows",
                              callback=self.indicator_list_selected)
        self.indicator_list_selection = 2

        gui.separator(indicator_filter_box)

        output_box = gui.widgetBox(self.controlArea, "Output", addSpace=True)
        gui.radioButtonsInBox(output_box,
                              self,
                              "output_type", ["Countries", "Time Series"],
                              "Rows",
                              callback=self.output_type_selected)
        self.output_type = 0

        gui.separator(output_box)
        # pylint: disable=duplicate-code
        gui.auto_commit(self.controlArea,
                        self,
                        "auto_commit",
                        "Commit",
                        box="Commit")
        gui.rubber(self.controlArea)

        # Main area

        gui.widgetLabel(self.mainArea, "Filter")
        self.filter_text = QtWidgets.QLineEdit(
            textChanged=self.filter_indicator_list)
        self.completer = QtWidgets.QCompleter(
            caseSensitivity=QtCore.Qt.CaseInsensitive)
        self.completer.setModel(QtCore.QStringListModel(self))
        self.filter_text.setCompleter(self.completer)

        spliter_v = QtWidgets.QSplitter(QtCore.Qt.Vertical, self.mainArea)

        self.mainArea.layout().addWidget(self.filter_text)
        self.mainArea.layout().addWidget(spliter_v)

        self.indicator_widget = IndicatorsTreeView(spliter_v, main_widget=self)

        splitter_h = QtWidgets.QSplitter(QtCore.Qt.Horizontal, spliter_v)

        self.description_box = gui.widgetBox(splitter_h, "Description")

        self.indicator_description = QtWidgets.QTextEdit()
        self.indicator_description.setReadOnly(True)
        self.description_box.layout().addWidget(self.indicator_description)

        box = gui.widgetBox(splitter_h, "Countries and Regions")
        self.country_tree = CountryTreeWidget(
            splitter_h,
            self.country_selection,
            default_select=True,
            default_colapse=True,
        )
        box.layout().addWidget(self.country_tree)
        self.country_tree.set_data(countries.get_countries_regions_dict())

        self.splitters = spliter_v, splitter_h

        for splitter, setting in zip(self.splitters, self.splitterSettings):
            splitter.splitterMoved.connect(self._splitter_moved)
            splitter.restoreState(setting)

        # self.resize(2000, 600)  # why does this not work

        self.progressBarInit()
Example #2
0
class OWWorldBankClimate(owwidget_base.OWWidgetBase):
    """World bank data widget for Orange."""
    # pylint: disable=invalid-name
    # Some names have to be invalid to override parent fields.
    # pylint: disable=too-many-ancestors
    # False positive from fetching all ancestors from QWWidget.
    # pylint: disable=too-many-instance-attributes
    # False positive from fetching all attributes from QWWidget.

    # Widget needs a name, or it is considered an abstract widget
    # and not shown in the menu.
    name = "WB Climate"
    icon = "icons/climate.png"
    outputs = [
        widget.OutputSignal("Data",
                            table.Table,
                            doc="Climate data from World bank Climate API")
    ]

    replaces = [
        "Orange.orangecontrib.wbd.widgets.OWWorldBankClimate",
    ]

    settingsList = [
        "auto_commit",
        "country_selection",
        "mergeSpots",
        "output_type"
        "splitterSettings",
    ]

    country_selection = Setting({})
    output_type = Setting(True)
    mergeSpots = Setting(True)
    auto_commit = Setting(False)
    use_country_names = Setting(False)

    include_intervals = Setting([])
    include_data_types = Setting([])

    def _data_type_setter(self, name, value):
        intervals = set(self.include_data_types) | {name}
        if not value:
            intervals.remove(name)
        self.include_data_types = list(intervals)
        logger.debug("New intervals: %s", self.include_data_types)

    def _interval_setter(self, name, value):
        intervals = set(self.include_intervals) | {name}
        if not value:
            intervals.remove(name)
        self.include_intervals = list(intervals)
        logger.debug("New intervals: %s", self.include_intervals)

    @property
    def include_month(self):
        return "month" in self.include_intervals

    @include_month.setter
    def include_month(self, value):
        self._interval_setter("month", value)

    @property
    def include_year(self):
        return "year" in self.include_intervals

    @include_year.setter
    def include_year(self, value):
        self._interval_setter("year", value)

    @property
    def include_decade(self):
        return "decade" in self.include_intervals

    @include_decade.setter
    def include_decade(self, value):
        self._interval_setter("decade", value)

    @property
    def include_temperature(self):
        return "tas" in self.include_data_types

    @include_temperature.setter
    def include_temperature(self, value):
        self._data_type_setter("tas", value)

    @property
    def include_precipitation(self):
        return "pr" in self.include_data_types

    @include_precipitation.setter
    def include_precipitation(self, value):
        self._data_type_setter("pr", value)

    splitterSettings = Setting((
        b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xea\x00'
        b'\x00\x00\xd7\x01\x00\x00\x00\x07\x01\x00\x00\x00\x02',
        b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xb5\x00'
        b'\x00\x02\x10\x01\x00\x00\x00\x07\x01\x00\x00\x00\x01'))

    def __init__(self):
        super().__init__()
        self._api = api_wrapper.ClimateAPI()
        self._init_layout()
        self.print_selection_count()
        try:
            self._check_server_status()
        except ConnectionError:
            pass

    def print_selection_count(self):
        """Update info widget with new selection count."""
        country_codes = self.get_country_codes()
        self.info_data["Selected countries"] = len(country_codes)
        self.print_info()

    def _init_layout(self):
        """Initialize widget layout."""

        # Control area
        info_box = gui.widgetBox(self.controlArea, "Info", addSpace=True)
        self._info_label = gui.widgetLabel(info_box, "Initializing\n\n")

        box = gui.vBox(self.controlArea, "Average intervals:")
        self.ch_month = gui.checkBox(box,
                                     self,
                                     "include_month",
                                     "Month",
                                     callback=self.commit_if)
        self.ch_year = gui.checkBox(box,
                                    self,
                                    "include_year",
                                    'Year',
                                    callback=self.commit_if)
        self.ch_decade = gui.checkBox(box,
                                      self,
                                      "include_decade",
                                      'Decade',
                                      callback=self.commit_if)

        box = gui.vBox(self.controlArea, "Data Types")
        gui.checkBox(box,
                     self,
                     "include_temperature",
                     "Temperature",
                     callback=self.commit_if)
        gui.checkBox(box,
                     self,
                     "include_precipitation",
                     'Precipitation',
                     callback=self.commit_if)

        output_box = gui.widgetBox(self.controlArea, "Output", addSpace=True)
        gui.radioButtonsInBox(output_box,
                              self,
                              "output_type", ["Countries", "Time Series"],
                              "Rows",
                              callback=self.output_type_selected)

        gui.checkBox(output_box,
                     self,
                     "use_country_names",
                     "Use Country names",
                     callback=self.commit_if)
        self.output_type = 0

        # pylint: disable=duplicate-code
        gui.separator(output_box)
        gui.auto_commit(self.controlArea,
                        self,
                        "auto_commit",
                        "Commit",
                        box="Commit")
        gui.rubber(self.controlArea)

        # Main area
        box = gui.widgetBox(self.mainArea, "Countries")
        self.country_tree = CountryTreeWidget(
            self.mainArea,
            self.country_selection,
            commit_callback=self.commit_if,
            default_colapse=True,
            default_select=False,
        )
        countriesdict = countries.get_countries_dict()
        if countriesdict is not None:
            self.country_tree.set_data(countriesdict)
        box.layout().addWidget(self.country_tree)
        self.resize(500, 400)  # why does this not work

    def output_type_selected(self):
        """Output type handle."""
        logger.debug("output type set to: %s", self.output_type)
        if self.output_type == 1:  # Time series
            self.ch_decade.setEnabled(False)
            self.ch_month.setEnabled(False)
            self.ch_year.setEnabled(False)
            self.include_year = True
            self.include_month = False
            self.include_decade = False
        else:
            self.ch_decade.setEnabled(True)
            self.ch_month.setEnabled(True)
            self.ch_year.setEnabled(True)
        self.commit_if()

    def _splitter_moved(self, *_):
        self.splitterSettings = [
            bytes(sp.saveState()) for sp in self.splitters
        ]

    def _check_big_selection(self):
        types = len(self.include_data_types) if self.include_data_types else 2
        intervals = len(
            self.include_intervals) if self.include_intervals else 2
        country_codes = self.get_country_codes()
        selected_countries = len(country_codes)
        if types * intervals * selected_countries > 100:
            self.info_data[
                "Warning"] = "Fetching data\nmight take a few minutes."
        else:
            self.info_data["Warning"] = None
        self.print_info()

    def commit_if(self):
        """Auto commit handler.

        This function must be called on every action that should trigger an
        auto commit.
        """
        self._check_big_selection()
        self.print_selection_count()
        super().commit_if()

    def _fetch_dataset(self, set_progress=None):
        """Fetch climate dataset."""

        set_progress(0)
        self._start_progerss_task()

        country_codes = self.get_country_codes()

        logger.debug("Fetch: selected country codes: %s", country_codes)
        climate_dataset = self._api.get_instrumental(
            country_codes,
            data_types=self.include_data_types,
            intervals=self.include_intervals)
        self._set_progress_flag = False
        return climate_dataset

    def _dataset_to_table(self, dataset):
        time_series = self.output_type == 1
        return dataset.as_orange_table(
            time_series=time_series,
            use_names=self.use_country_names,
        )

    def _dataset_progress(self, set_progress=None):
        while self._set_progress_flag:
            pages = self._api.progress["pages"]
            current_page = self._api.progress["current_page"]
            logger.debug("api progress: %s", self._api.progress)
            if pages > 0:
                progress = ((100 / pages) * (current_page - 1))
                logger.debug("calculated progress: %s", progress)
                set_progress(math.floor(progress))
            time.sleep(1)

    @staticmethod
    def _dataset_progress_exception(exception):
        logger.exception(exception)
class OWWorldBankIndicators(owwidget_base.OWWidgetBase):
    """World bank data widget for Orange."""
    # pylint: disable=invalid-name
    # Some names have to be invalid to override parent fields.
    # pylint: disable=too-many-ancestors
    # False positive from fetching all ancestors from QWWidget.
    # pylint: disable=too-many-instance-attributes
    # False positive from fetching all attributes from QWWidget.

    # Widget needs a name, or it is considered an abstract widget
    # and not shown in the menu.
    name = "WB Indicators"
    icon = "icons/wb_icon.png"
    outputs = [
        widget.OutputSignal("Data",
                            table.Table,
                            doc="Indicator data from World bank Indicator API")
    ]

    replaces = [
        "Orange.orangecontrib.wbd.widgets.OWWorldBankIndicators",
    ]

    indicator_list_map = collections.OrderedDict([
        (0, "All"),
        (1, "Common"),
        (2, "Featured"),
    ])

    settingsList = [
        "indicator_list_selection",
        "country_selection",
        "indicator_selection",
        "splitterSettings",
        "currentGds",
        "auto_commit",
        "output_type",
    ]

    country_selection = Setting({})
    indicator_selection = Setting([])
    indicator_list_selection = Setting(True)
    output_type = Setting(True)
    auto_commit = Setting(False)

    splitterSettings = Setting(
        (b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xea'
         b'\x00\x00\x00\xd7\x01\x00\x00\x00\x07\x01\x00\x00\x00\x02',
         b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xb5'
         b'\x00\x00\x02\x10\x01\x00\x00\x00\x07\x01\x00\x00\x00\x01'))

    def __init__(self):
        super().__init__()
        self._api = api_wrapper.IndicatorAPI()
        self._init_layout()
        self._check_server_status()

    def _init_layout(self):
        """Initialize widget layout."""

        # Control area
        info_box = gui.widgetBox(self.controlArea, "Info", addSpace=True)
        self._info_label = gui.widgetLabel(info_box, "Initializing\n\n")

        indicator_filter_box = gui.widgetBox(self.controlArea,
                                             "Indicators",
                                             addSpace=True)
        gui.radioButtonsInBox(indicator_filter_box,
                              self,
                              "indicator_list_selection",
                              self.indicator_list_map.values(),
                              "Rows",
                              callback=self.indicator_list_selected)
        self.indicator_list_selection = 2

        gui.separator(indicator_filter_box)

        output_box = gui.widgetBox(self.controlArea, "Output", addSpace=True)
        gui.radioButtonsInBox(output_box,
                              self,
                              "output_type", ["Countries", "Time Series"],
                              "Rows",
                              callback=self.output_type_selected)
        self.output_type = 0

        gui.separator(output_box)
        # pylint: disable=duplicate-code
        gui.auto_commit(self.controlArea,
                        self,
                        "auto_commit",
                        "Commit",
                        box="Commit")
        gui.rubber(self.controlArea)

        # Main area

        gui.widgetLabel(self.mainArea, "Filter")
        self.filter_text = QtWidgets.QLineEdit(
            textChanged=self.filter_indicator_list)
        self.completer = QtWidgets.QCompleter(
            caseSensitivity=QtCore.Qt.CaseInsensitive)
        self.completer.setModel(QtCore.QStringListModel(self))
        self.filter_text.setCompleter(self.completer)

        spliter_v = QtWidgets.QSplitter(QtCore.Qt.Vertical, self.mainArea)

        self.mainArea.layout().addWidget(self.filter_text)
        self.mainArea.layout().addWidget(spliter_v)

        self.indicator_widget = IndicatorsTreeView(spliter_v, main_widget=self)

        splitter_h = QtWidgets.QSplitter(QtCore.Qt.Horizontal, spliter_v)

        self.description_box = gui.widgetBox(splitter_h, "Description")

        self.indicator_description = QtWidgets.QTextEdit()
        self.indicator_description.setReadOnly(True)
        self.description_box.layout().addWidget(self.indicator_description)

        box = gui.widgetBox(splitter_h, "Countries and Regions")
        self.country_tree = CountryTreeWidget(
            splitter_h,
            self.country_selection,
            default_select=True,
            default_colapse=True,
        )
        box.layout().addWidget(self.country_tree)
        self.country_tree.set_data(countries.get_countries_regions_dict())

        self.splitters = spliter_v, splitter_h

        for splitter, setting in zip(self.splitters, self.splitterSettings):
            splitter.splitterMoved.connect(self._splitter_moved)
            splitter.restoreState(setting)

        # self.resize(2000, 600)  # why does this not work

        self.progressBarInit()

    def filter_indicator_list(self):
        """Set the proxy model filter and update info box."""
        filter_string = self.filter_text.text()
        proxy_model = self.indicator_widget.model()
        if proxy_model:
            strings = filter_string.lower().strip().split()
            proxy_model.setFilterFixedStrings(strings)
            self.print_info()

    def output_type_selected(self):
        self.commit_if()

    def basic_indicator_filter(self):
        return self.indicator_list_map.get(self.indicator_list_selection)

    def indicator_list_selected(self):
        """Update basic indicator selection.

        Switch indicator list selection between All, Common, and Featured.
        """
        value = self.basic_indicator_filter()
        logger.debug("Indicator list selected: %s", value)
        self.indicator_widget.fetch_indicators()

    def _splitter_moved(self, *_):
        self.splitterSettings = [
            bytes(sp.saveState()) for sp in self.splitters
        ]

    def _fetch_dataset(self, set_progress=None):
        """Fetch indicator dataset."""
        set_progress(0)
        self._start_progerss_task()

        country_codes = self.get_country_codes()

        if len(country_codes) > 250:
            country_codes = None
        logger.debug("Fetch: selected country codes: %s", country_codes)
        logger.debug("Fetch: selected indicators: %s",
                     self.indicator_selection)
        indicator_dataset = self._api.get_dataset(self.indicator_selection,
                                                  countries=country_codes)
        self._set_progress_flag = False
        return indicator_dataset

    def _dataset_to_table(self, dataset):
        time_series = self.output_type == 1
        return dataset.as_orange_table(time_series=time_series)

    @staticmethod
    def _fetch_dataset_exception(exception):
        logger.exception(exception)

    def _dataset_progress(self, set_progress=None):
        """Update dataset download progress.

        This function reads the progress state from the world bank API and sets
        the current widgets progress to that. All This thread should only read
        data and ask the GUI thread to update the progress for this to be
        thread safe.
        """
        while self._set_progress_flag:
            indicators = self._api.progress["indicators"]
            current_indicator = self._api.progress["current_indicator"]
            indicator_pages = self._api.progress["indicator_pages"]
            current_page = self._api.progress["current_page"]
            logger.debug("api progress: %s", self._api.progress)
            if indicator_pages > 0 and indicators > 0:
                progress = (((100 / indicators) *
                             (current_indicator - 1)) + (100 / indicators) *
                            (current_page / indicator_pages))
                logger.debug("calculated progress: %s", progress)
                set_progress(math.floor(progress))
            time.sleep(1)

    def _dataset_progress_exception(self, exception):
        logger.exception(exception)
        self.print_info()
Example #4
0
    def _init_layout(self):
        """Initialize widget layout."""

        # Control area
        info_box = gui.widgetBox(self.controlArea, "Info", addSpace=True)
        self._info_label = gui.widgetLabel(info_box, "Initializing\n\n")

        box = gui.vBox(self.controlArea, "Average intervals:")
        self.ch_month = gui.checkBox(box,
                                     self,
                                     "include_month",
                                     "Month",
                                     callback=self.commit_if)
        self.ch_year = gui.checkBox(box,
                                    self,
                                    "include_year",
                                    'Year',
                                    callback=self.commit_if)
        self.ch_decade = gui.checkBox(box,
                                      self,
                                      "include_decade",
                                      'Decade',
                                      callback=self.commit_if)

        box = gui.vBox(self.controlArea, "Data Types")
        gui.checkBox(box,
                     self,
                     "include_temperature",
                     "Temperature",
                     callback=self.commit_if)
        gui.checkBox(box,
                     self,
                     "include_precipitation",
                     'Precipitation',
                     callback=self.commit_if)

        output_box = gui.widgetBox(self.controlArea, "Output", addSpace=True)
        gui.radioButtonsInBox(output_box,
                              self,
                              "output_type", ["Countries", "Time Series"],
                              "Rows",
                              callback=self.output_type_selected)

        gui.checkBox(output_box,
                     self,
                     "use_country_names",
                     "Use Country names",
                     callback=self.commit_if)
        self.output_type = 0

        # pylint: disable=duplicate-code
        gui.separator(output_box)
        gui.auto_commit(self.controlArea,
                        self,
                        "auto_commit",
                        "Commit",
                        box="Commit")
        gui.rubber(self.controlArea)

        # Main area
        box = gui.widgetBox(self.mainArea, "Countries")
        self.country_tree = CountryTreeWidget(
            self.mainArea,
            self.country_selection,
            commit_callback=self.commit_if,
            default_colapse=True,
            default_select=False,
        )
        countriesdict = countries.get_countries_dict()
        if countriesdict is not None:
            self.country_tree.set_data(countriesdict)
        box.layout().addWidget(self.country_tree)
        self.resize(500, 400)  # why does this not work