Exemple #1
0
    def build_settings(self, req, result):

        self.settings = None
        self.settings = SettingsWithNoMenu()
        self.settings.on_config_change = self.on_config_change
        self.settings.register_type('string_long', SettingString)
        self.settings.register_type('num_int', SettingNumeric)
        self.settings.register_type('num', SettingNumeric)

        config = ConfigParser()
        print result['settings']
        config.setdefaults(self.popup.device_id, result['settings'])
        self.settings.add_json_panel(result['name'],
                                     config,
                                     data=dumps(result['settings_format']))
        self.add_widget(self.settings)

        buttons = BoxLayout(orientation='horizontal')
        buttons.add_widget(
            Button(text='Previous',
                   on_release=self.popup.previous_view,
                   height='50dp'))
        buttons.add_widget(
            Button(text='Next', on_release=self.popup.next_view,
                   height='50dp'))
        self.add_widget(buttons)
Exemple #2
0
 def settings_func(self, p):
     s = Settings()
     config = ConfigParser()
     try:
         config.setdefaults('EVM', {'school': self.school, 'names': self.temp, 'post': self.post, 'p_col': self.color, 'im_path': self.im_path, "code1": self.code1, "code2": self.code2, 'number':self.number})
     except:
         config.setdefaults('EVM', {'school': 'Unknown', 'names': self.temp, 'post': "Unknown", 'p_col': 'FFFFFF', 'im_path': self.im_path, "code1": "voting", "code2": "results", 'number':self.number})
     s.add_json_panel('EVM', config, data = self.json)
     s.bind(on_config_change = self.settings_change)
     setting = Popup(title = "Settings", content = s)
     s.bind(on_close = lambda *func: self.save_settings(s))
     setting.open()
Exemple #3
0
		def build_my_settings(settings, req, result):
		
			for settable in result:
				yeah_id = settable[0]
				settings_format = settable[1]
				my_settings = settable[2]
				
				print yeah_id, settings_format, my_settings
				
				config = ConfigParser()
				config.setdefaults(yeah_id, my_settings)
				settings.add_json_panel(my_settings['name'], config, data=dumps(settings_format))
Exemple #4
0
def load_config():
    global root, allow_uploads, port
    config = ConfigParser()
    config.read('serverconfig.ini')
    config.setdefaults('main', {
        'root': '/sdcard',
        'allow_uploads': False,
        'port': 11451
    })
    root = pathlib.Path(config['main']['root'])
    allow_uploads = config.getboolean('main', 'allow_uploads')
    port = config.getint('main', 'port')
Exemple #5
0
 def __init__(self, **kwargs):
     super(ServerSettings, self).__init__(**kwargs)
     config = ConfigParser()
     config.read('serverconfig.ini')
     config.setdefaults('main', {
         'root': '/sdcard',
         'allow_uploads': False,
         'port': 11451
     })
     s = SettingsWithNoMenu()
     s.add_json_panel('Server', config, resource_find('settings.json'))
     s.on_config_change = restart_server
     self.add_widget(s)
Exemple #6
0
    def build_config(self, config: ConfigParser) -> None:
        """
        Default section, key and value for config file before
        save configuration.

        :param config:
        :return:
        """
        config.setdefaults('permissions', get_permissions())
        config.setdefaults('info', get_general_info())

        config.setdefaults('ssid', DEFAULT_SSID)
        config.setdefaults('connection', DEFAULT_CONNECTION)
        config.setdefaults('device', DEFAULT_DEVICE)
Exemple #7
0
	def __init__(self, scenario_screen, block, *args, **kwargs):
		super(BlockSettingsPopup, self).__init__(*args, **kwargs)
		
		self.app = App.get_running_app()
		self.title = 'Block settings'
		self.block = block
		self.scenario_screen = scenario_screen
		
		self.settings = SettingsWithNoMenu()
		self.settings.on_config_change = self.on_config_change
		self.settings.register_type('string_long', SettingString)
		self.settings.register_type('num_int', SettingNumeric)
		self.settings.register_type('num', SettingNumeric)
		
		config = ConfigParser()
		config.setdefaults(block.yeah_id, block.settings)
		self.settings.add_json_panel(block.settings['name'], config, data=dumps(block.settings_format))		
		self.content = self.settings
Exemple #8
0
    def build_config(self, config: ConfigParser) -> None:
        """Public function builds self.config from src/sira.ini if it exists,
        otherwise sets self.config with default values and writes in
        src/sira.ini.

        [ensures]:  self.config is not None
                    [self.config has all attributes in its source file]
                    [At least, the following attributes exist:
                        ("Text", "user_name"),
                        ("Text", "cmd_identifier"),
                        ("Text", "font_size"),
                        ("Text", "font_name"),
                        ("Jira", "url"),
                        ("Jira", "timeout"),
                        ("Jira", "protocol"),
                        ("Option", "space_completion"),
                        ("Option", "tab_completion"),
                        ("Option", "options_per_line"),
                        ("Result", "max_result)
                    ]
        """
        text = {
            "cmd_identifier": ">",
            "font_size": "14",
            "font_name": "Monaco",
            "username": ""
        }
        jira = {
            "url": "lnvusjira.lenovonet.lenovo.local",
            "timeout": "5",
            "protocol": "https"
        }
        option = {
            "space_completion": "1",
            "tab_completion": "1",
            "options_per_line": "7"
        }
        result = {"max_result": "10"}
        config.setdefaults("Text", text)
        config.setdefaults("Jira", jira)
        config.setdefaults("Option", option)
        config.setdefaults("Result", result)
Exemple #9
0
    def __init__(self, scenario_screen, block, *args, **kwargs):
        super(BlockSettingsPopup, self).__init__(*args, **kwargs)

        self.app = App.get_running_app()
        self.title = 'Block settings'
        self.block = block
        self.scenario_screen = scenario_screen

        self.settings = SettingsWithNoMenu()
        self.settings.on_config_change = self.on_config_change
        self.settings.register_type('string_long', SettingString)
        self.settings.register_type('num_int', SettingNumeric)
        self.settings.register_type('num', SettingNumeric)

        config = ConfigParser()
        config.setdefaults(block.yeah_id, block.settings)
        self.settings.add_json_panel(block.settings['name'],
                                     config,
                                     data=dumps(block.settings_format))
        self.content = self.settings
Exemple #10
0
    def __init__(self, **kwargs):
        super(MyConnectDialog, self).__init__(**kwargs)

        self.register_type('buttons', SettingButtons)
        self.register_event_type('on_connect')

        config = ConfigParser()
        config.setdefaults(
            'common', {
                'conf_role': 'SERVER',
                'conf_transport': 'TLS',
                'conf_ip': '192.168.1.220',
                'conf_serport': 'COM1'
            })
        config.setdefaults('client', {
            'conf_user': '******',
            'conf_cert_chain': 'myhome-bundle.crt'
        })
        config.setdefaults('server', {
            'conf_serv_cert': 'rootca.crt',
            'conf_serv_key': 'secret/rootca.key'
        })
        self.myconfig = config
        try:
            config.read("i-spy.myconfig")
        except:
            print("No i-spy.myconfig")
        self.add_json_panel('IO device connect', config, data=json)
 def setUp(self):
     config = ConfigParser(name='app')
     config.setdefaults('fretboard', get_fretboard_defaults())
     config.setdefaults('fretboard_adv', get_fretboard_adv_defaults())
     config.setdefaults('window', get_window_defaults())
     # config.setdefaults('midi', get_midi_defaults())
     config.setdefaults('harmonic_definitions',
                        get_harmonic_definitions_defaults())
     self.tuning = P4Tuning(22)
     self.scale_config = Scales()
     self.chords_config = Chords()
     self.pattern_config = Patterns()
     self.pattern_mapping = P4TuningPatternMatcher(self.tuning,
                                                   self.chords_config,
                                                   self.scale_config,
                                                   self.pattern_config)
Exemple #12
0
	def build_settings(self, req, result):
		
		self.settings = None
		self.settings = SettingsWithNoMenu()
		self.settings.on_config_change = self.on_config_change
		self.settings.register_type('string_long', SettingString)
		self.settings.register_type('num_int', SettingNumeric)
		self.settings.register_type('num', SettingNumeric)
		
		config = ConfigParser()
		print result['settings']
		config.setdefaults(self.popup.device_id, result['settings'])
		self.settings.add_json_panel(result['name'], config, data=dumps(result['settings_format']))		
		self.add_widget(self.settings)
		
		buttons = BoxLayout(orientation = 'horizontal')
		buttons.add_widget(Button(text = 'Previous',
								  on_release = self.popup.previous_view,
								  height = '50dp'))
		buttons.add_widget(Button(text = 'Next',
								  on_release = self.popup.next_view,
								  height = '50dp'))
		self.add_widget(buttons)
Exemple #13
0
def test_nominal_recording_toolchain_case():

    config = ConfigParser()  # Empty but OK
    config.setdefaults("usersettings", {
        "record_gyroscope": 1,
        "record_gps": 1,
        "record_microphone": 1
    })

    key_storage_pool = FilesystemKeyStoragePool(INTERNAL_KEYS_DIR)
    encryption_conf = get_encryption_conf("test")
    toolchain = build_recording_toolchain(config,
                                          key_storage_pool=key_storage_pool,
                                          encryption_conf=encryption_conf)
    sensors_manager = toolchain["sensors_manager"]
    data_aggregators = toolchain["data_aggregators"]
    tarfile_aggregators = toolchain["tarfile_aggregators"]
    container_storage = toolchain["container_storage"]

    purge_test_containers()

    # TODO - make this a PURGE() methods of storage!!!
    # CLEANUP of already existing containers
    # for container_name in container_storage.list_container_names(sorted=True):
    #    container_storage._delete_container(container_name)
    # assert not len(container_storage)

    start_recording_toolchain(toolchain)
    time.sleep(2)
    stop_recording_toolchain(toolchain)

    for i in range(2):
        assert not sensors_manager.is_running
        for data_aggregator in data_aggregators:
            assert len(data_aggregator) == 0
        for tarfile_aggregator in tarfile_aggregators:
            assert len(tarfile_aggregator) == 0
        time.sleep(1)

    assert len(container_storage
               ) == 1  # Too quick recording to have container rotation
    (container_name, ) = container_storage.list_container_names(as_sorted=True)

    tarfile_bytestring = container_storage.decrypt_container_from_storage(
        container_name)

    tar_file = TarfileRecordsAggregator.read_tarfile_from_bytestring(
        tarfile_bytestring)
    tarfile_members = tar_file.getnames()
    assert len(tarfile_members) == 3

    # Gyroscope data

    gyroscope_filenames = [m for m in tarfile_members if "gyroscope" in m]
    assert len(gyroscope_filenames) == 1
    assert gyroscope_filenames[0].endswith(".json")

    json_bytestring = tar_file.extractfile(gyroscope_filenames[0]).read()
    gyroscope_data = load_from_json_bytes(json_bytestring)
    assert isinstance(gyroscope_data, list)
    assert len(gyroscope_data) >= 4
    assert gyroscope_data[0] == {
        "rotation_rate_x": None,
        "rotation_rate_y": None,
        "rotation_rate_z": None,
    }

    # GPS data

    microphone_filenames = [m for m in tarfile_members if "gps" in m]
    assert len(microphone_filenames) == 1
    assert microphone_filenames[0].endswith(".json")

    json_bytestring = tar_file.extractfile(microphone_filenames[0]).read()
    gyroscope_data = load_from_json_bytes(json_bytestring)
    # Fake data pushed by sensor
    assert gyroscope_data == [{
        'altitude': 2.2
    }, {
        'message_type': 'some_message_type',
        'status': 'some_status_value'
    }]

    # Microphone data

    microphone_filenames = [m for m in tarfile_members if "microphone" in m]
    assert len(microphone_filenames) == 1
    assert microphone_filenames[0].endswith(".mp4")

    mp4_bytestring = tar_file.extractfile(microphone_filenames[0]).read()
    assert mp4_bytestring == b"fake_microphone_recording_data"
class Settings:

    __defaults = {
        'kivy': {
            'log_level': 'debug',  # TODO: Change default to info
            'log_enable': 1,
            'log_dir': 'logs',
            'log_name': 'ps_%y-%m-%d_%_.txt',
            'log_maxfiles': 100
        },
        'data': {
            'dir': 'C:/pressure-data/',
            'ppr': 20
        },
        'com': {
            'port': 'COM1',
            'baudrate': 9600,
            'bytesize': '8',
            'parity': 'None',
            'stopbits': '1'
        },
        'calibration': {
            'user_point1': 0,
            'sensor_point1': 0,
            'user_point2': 2,
            'sensor_point2': 1024
        }
    }

    def __init__(self):
        self.config = ConfigParser()
        self.widget = SettingsWithNoMenu()

    def load(self, filename):
        for k, v in self.__defaults.items():
            self.config.setdefaults(k, v)
        self.config.read(filename)
        self.config.write()

        Config.read(filename)

        Logger.info('Settings: Loaded setting file: %s', filename)

        Logger.debug('Settings: Setting up panel')
        self.panel = self.widget.create_json_panel('Settings',
                                                   self.config,
                                                   data=self.windgetconfigdata)
        self.widget.children[0].add_widget(self.panel)

        Logger.debug('Settings: Setting options')
        self.setPanelOptions('port', SerialAdapter.getPortNames())
        self.setPanelOptions('bytesize', SerialAdapter.BYTESIZE.keys())
        self.setPanelOptions('parity', SerialAdapter.PARITY.keys())
        self.setPanelOptions('stopbits', SerialAdapter.STOPBITS.keys())

    def updateAvailablePorts(self):
        Logger.debug('Settings: Setting port options')
        self.setPanelOptions('port', SerialAdapter.getPortNames())

    def getPanelSetting(self, key):
        return next(
            (x for x in self.panel.children if not isinstance(x, SettingTitle)
             and not isinstance(x, Label) and x.key == key), None)

    def setPanelOptions(self, key, options):
        s = self.getPanelSetting(key)
        if s != None:
            s.options = options

    def getWidget(self):
        return self.widget

    def addCallback(self, callback, section=None, key=None):
        Logger.debug('Settings: Adding callback: %s, %s', section, key)
        self.config.add_callback(callback, section, key)
        if key != None:
            callback(section, key, self.get(section, key))

    def get(self, section, key):
        return self.config.get(section, key)

    def set(self, section, key, value):
        return self.config.set(section, key, value)

    def getDefault(self, section, key):
        return self.__defaults[section][key]

    def saveConfig(self):
        self.config.write()

    windgetconfigdata = """[
Exemple #15
0
class MainApp(MDApp):
    # Language: get system locale.
    lang = StringProperty(locale.getdefaultlocale()[0][:2])
    # For showing/hiding search widget.
    is_search_focused = BooleanProperty(False)
    is_first_started = BooleanProperty(True)
    app_primary_palette = StringProperty("Teal")

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.selected_dampers = [
        ]  # Every damper selected by MyRightCheckbox add to this list.
        self.all_dampers_in_container = [
        ]  # Consists of all adding DamperListItem.
        self.damper = None
        self.dampers = [
        ]  # Has all getting dampers (class Damper) from the DB.
        self.found_dampers = []  # Has all found in searching dampers.
        self.menu_sort = None
        self.menu_dots = None
        # For exit on double tap on the buttnon back.
        self.is_back_clicked_once = False
        # My config.
        self.config = ConfigParser()
        # App theme.
        self.primary_palette = "Teal"
        self.accent_palette = "Amber"
        self.theme_style = "Light"
        # To avoid multi chosen right_checkbox_lang.
        self.lang_checkboxes_dict = dict()
        # Handling the back button.
        Window.bind(on_keyboard=self.key_input)
        # The current target TextInput widget requesting the keyboard
        # is presented just above the soft keyboard.
        Window.softinput_mode = "below_target"

    def build_config(self, config):
        """Default config."""
        self.config.setdefaults(
            "currenttheme", {
                "primary_palette": "Teal",
                "accent_palette": "Amber",
                "theme_style": "Light"
            })
        self.config.setdefaults("applanguage", {"language": self.lang})

    def save_config(self):
        """Save the App config."""
        self.config.set("currenttheme", "primary_palette",
                        self.primary_palette)
        self.config.set("currenttheme", "accent_palette", self.accent_palette)
        self.config.set("currenttheme", "theme_style", self.theme_style)
        self.config.set("applanguage", "language", self.lang)
        self.config.write()

    def my_load_config(self):
        """Load the App config."""
        self.primary_palette = self.config.get("currenttheme",
                                               "primary_palette")
        self.accent_palette = self.config.get("currenttheme", "accent_palette")
        self.theme_style = self.config.get("currenttheme", "theme_style")
        self.lang = self.config.get("applanguage", "language")

    def apply_mytoolbar_theme(self):
        """Apply loaded theme for MyToolbar."""
        self.theme_cls.primary_palette = self.primary_palette
        self.theme_cls.accent_palette = self.accent_palette
        self.theme_cls.theme_style = self.theme_style

    def build(self):
        # Loading and applying the App config.
        # Impossible to execute self.my_load_config() in __init__
        # because of configparser.NoSectionError: No section: 'currenttheme'.
        self.my_load_config()
        # Instantiate an instance of Lang.
        self.tr = Lang(self.lang)
        self.title = self.tr._("Dampers")

        self.menu_items_dots = [{
            "text": self.tr._("Select all"),
            "icon": "select-all"
        }, {
            "text": self.tr._("Cancel all selection"),
            "icon": "select-off"
        }, {
            "text": self.tr._("Add type"),
            "icon": "plus"
        }, {
            "text": self.tr._("Delete/Edit type"),
            "icon": "delete-outline"
        }, {
            "text": self.tr._("Add damper"),
            "icon": "plus"
        }, {
            "text": self.tr._("Edit selected damper"),
            "icon": "square-edit-outline"
        }, {
            "text": self.tr._("Delete selected dampers"),
            "icon": "delete-outline"
        }, {
            "text": self.tr._("Backup Database"),
            "icon": "content-save-outline"
        }, {
            "text": self.tr._("Restore Database"),
            "icon": "backup-restore"
        }, {
            "text": self.tr._("Clear DB"),
            "icon": "delete-forever-outline"
        }, {
            "text": self.tr._("Language"),
            "icon": "web"
        }, {
            "text": self.tr._("Change theme"),
            "icon": "theme-light-dark"
        }, {
            "text": self.tr._("Exit"),
            "icon": "exit-to-app"
        }]
        # Dict to process callback_menu_dots like switch in C++.
        self.dict_menu_dots_funcs = {
            self.tr._("Select all"):
            self.select_all,
            self.tr._("Cancel all selection"):
            self.cancel_all_selection,
            self.tr._("Add type"):
            partial(self.change_screen, "add_type_screen"),
            self.tr._("Delete/Edit type"):
            partial(self.change_screen, "delete_edit_type_screen"),
            self.tr._("Add damper"):
            partial(self.change_screen, "add_damper_screen"),
            self.tr._("Edit selected damper"):
            self.edit_selected_damper,
            self.tr._("Delete selected dampers"):
            self.show_delete_dampers_dialog,
            self.tr._("Backup Database"):
            self.choose,
            self.tr._("Restore Database"):
            partial(self.choose, False),
            self.tr._("Clear DB"):
            self.show_clear_db_dialog,
            self.tr._("Language"):
            partial(self.change_screen, "language_screen"),
            self.tr._("Change theme"):
            self.show_themepicker,
            self.tr._("Exit"):
            self.stop
        }

        self.menu_items_sort = [{
            "text": self.tr._("By 'number'"),
            "icon": "sort-numeric"
        }, {
            "text": self.tr._("By 'location'"),
            "icon": "format-columns"
        }, {
            "text": self.tr._("By 'check date'"),
            "icon": "calendar-month"
        }, {
            "text": self.tr._("By 'is released'"),
            "icon": "check-outline"
        }, {
            "text": self.tr._("By 'no order'"),
            "icon": "not-equal-variant"
        }
                                # "icon": "sort-variant-remove"}
                                ]
        # Dict to process callback_menu_sort like switch in C++..
        self.dict_menu_sort_funcs = {
            self.tr._("By 'number'"):
            partial(self.get_dampers, "by number"),
            self.tr._("By 'location'"):
            partial(self.get_dampers, "by location"),
            self.tr._("By 'check date'"):
            partial(self.get_dampers, "by check date"),
            self.tr._("By 'is released'"):
            partial(self.get_dampers, "by is released"),
            self.tr._("By 'no order'"):
            self.get_dampers
        }
        # Handling the back button.
        # Window.bind(on_keyboard=self.key_input)
        # The current target TextInput widget requesting the keyboard
        # is presented just above the soft keyboard.
        # Window.softinput_mode = "below_target"

        return Container()

    def on_start(self):
        if platform == "android":
            # Runtime permissions.
            from android.permissions import request_permissions, Permission
            request_permissions([
                Permission.WRITE_EXTERNAL_STORAGE,
                Permission.READ_EXTERNAL_STORAGE
            ])

        self.apply_mytoolbar_theme()

        self.screen_manager = self.root.ids["screen_manager"]
        self.home_screen = self.root.ids["home_screen"]
        self.dampers_container = self.home_screen.ids["dampers_container"]
        self.tf_search = self.home_screen.ids["tf_search"]
        self.container = self.home_screen.ids["container"]
        self.lang_screen = self.root.ids["language_screen"]
        # For passing old_damper info into the EditDamperScreen.
        self.edit_damper_screen = self.root.ids["edit_damper_screen"]
        # Creating MyToolbar dots and sort menus.
        self.menu_dots = MDDropdownMenu(
            caller=self.home_screen.ids["tb_home"].ids["ibtn_dots"],
            items=self.menu_items_dots,
            callback=self.callback_menu_dots,
            position="bottom",
            hor_growth="right",
            # ver_growth="down",
            width_mult=10)
        self.menu_sort = MDDropdownMenu(
            caller=self.home_screen.ids["tb_home"].ids["ibtn_sort"],
            items=self.menu_items_sort,
            callback=self.callback_menu_sort,
            position="bottom",
            hor_growth="right",
            # ver_growth="up",
            width_mult=7)
        self.change_toolbar_theme()

        self.add_lang_checkboxes_into_dict()
        self.lang_checkboxes_dict[self.lang].active = True

        self.get_dampers()
        self.is_first_started = False

    def add_lang_checkboxes_into_dict(self):
        """
        Store all right_checkbox_(lang) into the lang_checkboxes_dict
        to control which right_checkbox is chosen.
        """
        self.lang_checkboxes_dict["en"] = self.lang_screen.ids[
            "right_checkbox_en"]
        self.lang_checkboxes_dict["ru"] = self.lang_screen.ids[
            "right_checkbox_ru"]

    def on_stop(self):
        """Save config."""
        self.save_config()

    def on_pause(self):
        return True

    def on_resume(self):
        pass

    def on_lang(self, instance, lang):
        """User changed language."""
        # Skip the first tr.switch_lang
        # because self.tr is not defined yet.
        # The first switch will be in the build method: self.tr = Lang(self.lang)
        # after self.my_load_config().
        if not self.is_first_started:
            self.tr.switch_lang(lang)

            dialog = MDDialog(title=self.tr._("Change language"),
                              size_hint=(.7, .4),
                              text_button_ok=self.tr._("Ok"),
                              auto_dismiss=False,
                              events_callback=self.stop,
                              text=self.tr._(
                                  "You have to restart the app"
                                  "\nto change the language completely."))
            dialog.open()

    def key_input(self, window, key, scancode, codepoint, modifier):
        def reset_btn_back_clicked(*args):
            """
            Set is_back_clicked_once to False.
            There was no double click on the button back for exit.
            """
            self.is_back_clicked_once = False

        if key == 27:  # (the back button key is 27, codepoint is 270).
            if self.screen_manager.current != "home_screen":
                self.change_screen("home_screen")
            elif self.is_back_clicked_once:
                self.stop()
            else:
                self.is_back_clicked_once = True
                toast(self.tr._("Tap BACK again to exit"), duration=1)
                Clock.schedule_once(reset_btn_back_clicked, 3)

            return True
        return False

    def callback_menu_sort(self, instance):
        """
        Check what item in the menu_sort pressed and
        do the action according pressed menu item.
        Actions are in the self.dict_menu_sort.
        """
        self.dict_menu_sort_funcs.get(instance.text)()

    def callback_menu_dots(self, instance):
        """
        Check what item in the menu_dots pressed and
        do the action according pressed menu item.
        Actions are in the self.dict_menu_dots.
        """
        self.dict_menu_dots_funcs.get(instance.text)()

    def get_dampers(self, order="no order", *args):
        """
        Get all dampers from the DB and store them into self.dampers.
        :param order: str for sorting can be:
                                    "by number", "by location",
                                    "by check date", by is released",
                                    "no order"
        """
        self.damper = Damper()
        try:
            self.dampers = self.damper.get_dampers(order)
        except sqlite3.DatabaseError:
            toast(self.tr._("Can't get dampers from the DB"))
        else:
            # Not to show_dampers in the first start
            # because it'll be done in change_screen.
            if not self.is_first_started:
                self.show_dampers()

    def show_dampers(self, is_search=False, *args):
        """
        Get all dampers from the DB and show them.
        :param args: for Clock.schedule_once(self.set_field_focus, 1) in self.clear_db
        :param is_search: if True show only found dampers in self.found_dampers.
        """
        # Hide search if not search.
        if not is_search:
            self.hide_search()

        if self.all_dampers_in_container:
            for damper in self.all_dampers_in_container:
                self.dampers_container.remove_widget(damper)

        # Clear all selections.
        self.selected_dampers.clear()
        self.all_dampers_in_container.clear()

        # If search show only found dampers in self.found_dampers.
        dampers = self.found_dampers if is_search else self.dampers
        if self.dampers:
            for self.damper in dampers:
                # Format for output damper data.
                released = "Released" if self.damper.is_released else "Not released"
                text = "{}        {}".format(self.damper.number,
                                             self.damper.location)
                secondary_text = "{}       {}".format(self.damper.check_date,
                                                      released)
                tertiary_text = "{}          {}".format(
                    self.damper.d_type, self.damper.notes)

                a_damper_list_item = DamperListItem(
                    text=text,
                    secondary_text=secondary_text,
                    tertiary_text=tertiary_text)
                self.dampers_container.add_widget(a_damper_list_item)
                # Add all adding DamperListItem to the list for
                # getting access to right_checkbox_dampers in the future.
                self.all_dampers_in_container.append(a_damper_list_item)
        else:
            # Clock.schedule_once(lambda x: (toast("No dampers in the DB")), 4)
            toast(self.tr._("No dampers in the DB"))

    def show_search(self, *args):
        """Show search."""
        self.tf_search.focused = True
        self.is_search_focused = True
        # Slide tf_search top down from .96 to .9
        anim_search = Animation(top_hint_search=.9)
        anim_search.start(self.tf_search)

        # Slide container(GridLayout) top down from .9 to .84
        anim_container = Animation(top_hint_container=.84)
        anim_container.start(self.container)

    def hide_search(self, *args):
        """Hide search."""
        self.is_search_focused = False
        # Clear tf_search when hiding.
        self.tf_search.text = ""
        # Slide tf_search top up from .9 to .96
        anim_search = Animation(top_hint_search=.96)
        anim_search.start(self.tf_search)

        # Slide container(GridLayout) top up from .84 to .9
        anim_container = Animation(top_hint_container=.9)
        anim_container.start(self.container)

    def search_text_changed(self, finding_text):
        """
        Search dampers by finding_text,
        add filtered dampers to the self.found_dampers
        and output them in self.show_dampers.
        :param finding_text:
        """
        self.found_dampers = []
        for self.damper in self.dampers:
            if (finding_text in self.damper.number
                    or finding_text in self.damper.location
                    or finding_text in self.damper.check_date):
                self.found_dampers.append(self.damper)
        self.show_dampers(is_search=True)

    def choose(self, is_backup=True, *args):
        """
        Call plyer filechooser API to run a filechooser Activity.
        """
        if platform == "android":
            from android.permissions import request_permissions, Permission, check_permission
            # Check if the permissions still granted.
            if not check_permission(Permission.WRITE_EXTERNAL_STORAGE):
                request_permissions([Permission.WRITE_EXTERNAL_STORAGE])
            else:
                filechooser.open_file(on_selection=self.backup_db
                                      if is_backup else self.restore_db)
        else:
            filechooser.open_file(
                on_selection=self.backup_db if is_backup else self.restore_db)

    def backup_db(self, selection):
        """Backup Database."""
        # chosen_dir = filechooser.choose_dir(title="Choose directory")  # Doesn't work on Android (why?).
        chosen_dirname = os.path.dirname(selection[0])
        now = datetime.now()
        now_datetime = ("{}-{}-{}_{}-{}-{}".format(now.year,
                                                   str(now.month).zfill(2),
                                                   str(now.day).zfill(2),
                                                   str(now.hour).zfill(2),
                                                   str(now.minute).zfill(2),
                                                   str(now.second).zfill(2)))
        # dirname = os.path.dirname(__file__)  # doesn't work on Android.
        dirname = os.getcwd()
        src_db_path = "{}{}dampers.db".format(dirname, os.sep)
        dst_filename = "{}{}{}_{}".format(chosen_dirname, os.sep, now_datetime,
                                          "dampers.db")
        try:
            shutil.copyfile(src_db_path, dst_filename)
        except OSError as err:
            toast(str(err))
            # toast("SaveBackupError")
        else:
            toast(self.tr._("Backup file saved"))

    def restore_db(self, selection):
        """Restore Database."""
        # dst_db_path = os.path.dirname(__file__)   # doesn't work on Android.
        dst_db_path = os.getcwd()
        try:
            shutil.copyfile(selection[0],
                            "{}{}{}".format(dst_db_path, os.sep, "dampers.db"))
        except OSError as err:
            toast(str(err))
            # toast("RestoreBackupError")
        else:
            toast(self.tr._("Backup file restored"))
            # Get and show dampers after restoring.
            self.get_dampers()

    def show_themepicker(self, *args):
        picker = MDThemePicker()
        picker.open()
        picker.bind(on_dismiss=self.themepicker_dismiss)

    def themepicker_dismiss(self, instance):
        """
        Changing the App primary_palette, accent_palette and theme_style.
        :param instance: current MDThemePicker.
        """
        self.primary_palette = self.theme_cls.primary_palette
        self.accent_palette = self.theme_cls.accent_palette
        self.theme_style = self.theme_cls.theme_style

        self.change_toolbar_theme()
        self.save_config()

    def change_toolbar_theme(self):
        """Changing  tb_primary_palette for all MyToolbars."""
        self.home_screen.ids[
            "tb_home"].tb_primary_palette = self.primary_palette
        self.root.ids["add_type_screen"].ids[
            "tb_addedit"].tb_primary_palette = self.primary_palette
        self.root.ids["edit_type_screen"].ids[
            "tb_addedit"].tb_primary_palette = self.primary_palette
        self.root.ids["delete_edit_type_screen"].ids[
            "tb_deleteedittype"].tb_primary_palette = self.primary_palette
        self.root.ids["add_damper_screen"].ids[
            "tb_addedit"].tb_primary_palette = self.primary_palette
        self.root.ids["edit_damper_screen"].ids[
            "tb_addedit"].tb_primary_palette = self.primary_palette
        self.root.ids["language_screen"].ids[
            "tb_addedit"].tb_primary_palette = self.primary_palette

    def change_screen(self, screen_name, *args):
        if screen_name == "home_screen":
            self.tf_search.focused = False
            self.tf_search.text = ""
            self.get_dampers()

        self.screen_manager.current = screen_name

    def show_delete_dampers_dialog(self, *args):
        """Show delete damper dialog."""
        if self.selected_dampers:
            dialog = MDDialog(title=self.tr._("Delete damper"),
                              size_hint=(.7, .4),
                              text_button_ok=self.tr._("Delete"),
                              text_button_cancel=self.tr._("Cancel"),
                              auto_dismiss=False,
                              events_callback=self.delete_selected_dampers,
                              text=self.tr._(
                                  "This action will delete selected dampers"
                                  "\nfrom the Database."
                                  "\nDo you really want to do this?"))
            dialog.open()

    def delete_selected_dampers(self, text_of_selection, *args):
        """
        Delete selected items
        from DB and _item_container.
        """
        if text_of_selection == self.tr._("Delete"):
            # if self.selected_dampers:
            for selected_damper in self.selected_dampers:
                # Get the damper the_number.
                damper_number = selected_damper.text.split()[0]
                damper = Damper()
                try:
                    damper.delete_damper(damper_number)
                except sqlite3.DatabaseError:
                    toast("DeleteDamperError")
                else:
                    self.dampers_container.remove_widget(selected_damper)
            toast(self.tr._("Deleted"))
            self.get_dampers()

    def edit_selected_damper(self, *args):
        """Edit selected damper."""
        if self.selected_dampers:  # if self.selected_dampers is not empty.
            if len(self.selected_dampers) > 1:
                toast(self.tr._("Select one for editing"))
            else:
                number_location = self.selected_dampers[0].text.split()
                checkdate_isreleased = self.selected_dampers[
                    0].secondary_text.split()
                dtype_notes = self.selected_dampers[0].tertiary_text.split()

                self.edit_damper_screen.old_number = number_location[0]
                self.edit_damper_screen.old_location = number_location[1]
                self.edit_damper_screen.old_check_date = checkdate_isreleased[
                    0]
                self.edit_damper_screen.old_is_released = True if checkdate_isreleased[
                    1] == "Released" else False
                self.edit_damper_screen.old_d_type = dtype_notes[0]
                self.edit_damper_screen.old_notes = dtype_notes[1] if len(
                    dtype_notes) == 2 else ""

                self.change_screen("edit_damper_screen")

    def show_clear_db_dialog(self, *args):
        """Show clear DB dialog."""
        dialog = MDDialog(
            title=self.tr._("Clear Database"),
            size_hint=(.7, .4),
            text_button_ok=self.tr._("Clear"),
            text_button_cancel=self.tr._("Cancel"),
            auto_dismiss=False,
            events_callback=self.clear_db,
            text=self.tr._(
                "[color={}]This action will delete "
                "\n[b]ALL[/b] data from the Database."
                "\nDo you really want to do this?[/color]").format("#FF0000"))

        dialog.open()

    def clear_db(self, text_of_selection, *args):
        """Delete ALL date from the DB."""
        if text_of_selection == self.tr._("Clear"):
            damper = Damper()
            try:
                damper.clear_db()
            except sqlite3.DatabaseError:
                toast("ClearDBError")
            else:
                toast(self.tr._("Cleared"))
                # Delay for showing toast("Cleared")
                Clock.schedule_once(self.get_dampers, 1)

    def select_all(self, *args):
        """Select all elements."""
        for damper_list_item in self.all_dampers_in_container:
            damper_list_item.ids["right_checkbox_dampers"].active = True

    def cancel_all_selection(self, *args):
        """Cancel selection of all elements."""
        for damper_list_item in self.all_dampers_in_container:
            damper_list_item.ids["right_checkbox_dampers"].active = False

    def add_into_selected_dampers(self, instance):
        """Add selected item into the list: selected_dampers."""
        self.selected_dampers.append(instance)

    def del_from_selected_dampers(self, instance):
        """Delete selected item from the list: selected_dampers."""
        self.selected_dampers.remove(instance)
Exemple #16
0
 def build_config(self, config: ConfigParser):
     config.setdefaults("customization", {"button_per_scroll": 4})
Exemple #17
0
class StoryBook(Widget):
    # This story's title
    title = StringProperty(None)

    # The story's library
    library_parent = StringProperty(None)

    # The story's library number
    story_number = NumericProperty(None)

    # The current set page by name
    current_page = StringProperty("title")

    # The current set page by number
    current_page_no = NumericProperty(0)

    # List of all pages by name
    pages = ListProperty()

    # The parsed story config
    story_config = ObjectProperty(None)

    # The defaults file
    story_config_file = StringProperty(None)

    # Where is the title media?
    title_media_location = StringProperty(None)

    def __init__(self, **kwargs):
        """
        Initialize starting values. Set kwargs values.
        Set current page to title and page number to 0.
        :param kwargs:
        title: The title of this story
        library: The name of this story's library
        story_number: This story's library number
        """
        super(StoryBook, self).__init__(**kwargs)
        self.title = kwargs['title']
        self.library_parent = kwargs['library']
        self.story_number = kwargs['number']

        self.current_page = "title"
        self.current_page_no = 0
        self.pages = []
        self.story_config_file = ""

    def load_story_config(self, library_dir):
        self.story_config = ConfigParser()
        story_file_loc = library_dir.joinpath(self.title + '.ini')
        if not story_file_loc.is_file():
            self.story_config.setdefaults('metadata',
                                          get_metadata_defaults(self.title, self.library_parent))
            self.story_config.setdefaults('title',
                                          get_page_defaults(self.title))

        self.story_config_file = str(story_file_loc)

        # Set config from story's config file.
        self.story_config.read(str(self.story_config_file))
        if self.story_config.get('metadata', 'story') != self.title:
            self.story_config.set('metadata', 'story', self.title)

        if self.story_config.get('metadata', 'library') != self.library_parent:
            self.story_config.set('metadata', 'library', self.library_parent)

        # Find the media location for this story's title page
        self.title_media_location = self.story_config.get('title', 'media_location')

        # Find all the pages
        self.pages = ['title'] + [x.strip() for x in self.story_config.get('metadata', 'pages').split(',')]
        self.story_config.write()

    def start_page(self):
        """
        Updates the current page to be the first page
        :return:
        """
        self.current_page_no = 0
        self.current_page = self.pages[0]

    def next_page(self):
        """
        Updates the current page to be the next page
        """
        self.current_page_no = min(self.current_page_no + 1, len(self.pages) - 1)
        self.current_page = self.pages[self.current_page_no]

    def previous_page(self):
        """
        Updates the current page to be the previous page
        """
        self.current_page_no = min(self.current_page_no - 1, len(self.pages) - 1)
        self.current_page = self.pages[self.current_page_no]

    def get_story_value(self, page, value):
        return self.story_config.get(page, value)

    def get_title_image(self):
        media_location = self.get_story_value(self.pages[0], 'media_location')
        if len(media_location) == 0:
            media_location = 'images/background.png'

        return media_location

    def get_story_media(self):
        media_location = self.get_story_value(self.current_page, 'media_location')
        if len(media_location) == 0:
            media_location = 'images/background.png'

        return media_location

    def get_story_text(self):
        return self.get_story_value(self.current_page, 'text')
Exemple #18
0
class RenderGUI(Widget):
    rend = None
    azimuth = NumericProperty(20.0)
    altitude = NumericProperty(20.0)
    distance_per_pixel = NumericProperty(0.0)
    stepsize = NumericProperty(0.0)
    x_pixel_offset = NumericProperty(0)
    y_pixel_offset = NumericProperty(0)
    rend_opacity = BooleanProperty(False)
    channel = NumericProperty(0)
    log_offset = NumericProperty(6.0)
    cbar_num = NumericProperty(10)
    snap = NumericProperty(0)
    rendermode = Mode.intensity
    spect_analyzer = spectAnlys.Analyzer()
    nlamb = NumericProperty(41)
    cbsize = (30, 3000)
    asym_sep = NumericProperty(0.0)
    asym_width = NumericProperty(0.0)
    noise_snr = NumericProperty(999.)

    helptext = ('Pan l/r: a/d\n'
                'Tilt u/d: w/s\n'
                'zoom in/out: j/k\n'
                'Shift l/r: [left]/[right]\n'
                'Shift u/d: [up]/[down]\n'
                'Recenter shift: c\n'
                'Dynamic range inc/dec: i/u\n'
                'Stepsize inc/dec: ./,\n'
                'Toggle opacity: o\n'
                'Change timestep: [/]')
    initialized = False

    def __init__(self, rend, **kwargs):
        self.texture = Texture.create(size=BUF_DIMENSIONS)
        self.texture_size = BUF_DIMENSIONS
        self.cbtex = Texture.create(size=self.cbsize)
        super(RenderGUI, self).__init__(**kwargs)

        self.rend = rend
        self.buffer_array = np.empty(BUF_DIMENSIONS[::-1] + (4, ), dtype='uint8')
        self.distance_per_pixel = self.rend.distance_per_pixel
        self.stepsize = self.rend.stepsize

        self.x_pixel_offset = rend.x_pixel_offset
        self.y_pixel_offset = rend.y_pixel_offset
        self.snap = self.rend.snap

        self.config = ConfigParser()
        self.channellist = [os.path.basename(os.path.splitext(a)[0]) for a in self.rend.channellist()]
        self.config.setdefaults('renderer', {'rendermode': self.rendermode,
                                             'channel': self.channellist[0],
                                             'snap': self.rend.snap,
                                             'nlamb': self.nlamb,
                                             'opacity': int(self.rend_opacity),
                                             'altitude': self.altitude,
                                             'azimuth': self.azimuth,
                                             'distance_per_pixel': self.distance_per_pixel,
                                             'stepsize': self.stepsize,
                                             'noise_snr': self.noise_snr})
        self.config.setdefaults('display', {'log_offset': self.log_offset,
                                            'cbar_num': self.cbar_num,
                                            'asym_sep': self.asym_sep,
                                            'asym_width': self.asym_width})

        self.spanel = SettingsPanel(settings=self.s, title='Render Settings', config=self.config)
        self.s.interface.add_panel(self.spanel, 'Render Settings', self.spanel.uid)

        self.dpanel = SettingsPanel(settings=self.s, title='Display Settings', config=self.config)
        self.s.interface.add_panel(self.dpanel, 'Display Settings', self.dpanel.uid)

        self.mode_opt = SettingOptions(title='Render Mode',
                                       desc='What to simulate and display',
                                       key='rendermode',
                                       section='renderer',
                                       options=[Mode.__dict__[x] for x in dir(Mode) if not x.startswith('_')],
                                       panel=self.spanel)
        self.spanel.add_widget(self.mode_opt)

        self.chan_opt = SettingOptions(title='Channel',
                                       desc='Emissions channel to select',
                                       key='channel',
                                       section='renderer',
                                       options=self.channellist,
                                       panel=self.spanel)
        self.spanel.add_widget(self.chan_opt)

        self.snap_opt = SettingNumeric(title='Snap',
                                       desc='Snap number to select',
                                       key='snap',
                                       section='renderer',
                                       panel=self.spanel)
        self.spanel.add_widget(self.snap_opt)

        self.nlamb_opt = SettingNumeric(title='NLamb',
                                        desc='Number of frequencies to sample during spectra calculations',
                                        key='nlamb',
                                        section='renderer',
                                        panel=self.spanel)
        self.spanel.add_widget(self.nlamb_opt)

        self.opa_opt = SettingBoolean(title='Opacity',
                                      desc='Whether or not to enable opacity in the simulation',
                                      key='opacity',
                                      section='renderer',
                                      panel=self.spanel)
        self.spanel.add_widget(self.opa_opt)

        self.alt_opt = SettingNumeric(title='Altitude',
                                      desc='The POV angle above horizontal',
                                      key='altitude',
                                      section='renderer',
                                      panel=self.spanel)
        self.spanel.add_widget(self.alt_opt)

        self.azi_opt = SettingNumeric(title='Azimuth',
                                      desc='The POV angle lateral to the x-axis',
                                      key='azimuth',
                                      section='renderer',
                                      panel=self.spanel)
        self.spanel.add_widget(self.azi_opt)

        self.dpp_opt = SettingNumeric(title='Distance per Pixel',
                                      desc='Distance in simulation between pixels in km, specifies zoom',
                                      key='distance_per_pixel',
                                      section='renderer',
                                      panel=self.spanel)
        self.spanel.add_widget(self.dpp_opt)

        self.stp_opt = SettingNumeric(title='Step Size',
                                      desc='Magnitude of the integration stepsize, increase for performance',
                                      key='stepsize',
                                      section='renderer',
                                      panel=self.spanel)
        self.spanel.add_widget(self.stp_opt)

        self.noise_snr_opt = SettingNumeric(title='Spectral SNR',
                                            desc=u'Spectral signal to noise ratio, in dB\u2014to disable, set to 999',
                                            key='noise_snr',
                                            section='renderer',
                                            panel=self.spanel)
        self.spanel.add_widget(self.noise_snr_opt)

        self.range_opt = SettingNumeric(title='Dynamic Range',
                                        desc='Orders of magnitude to span in display',
                                        key='log_offset',
                                        section='display',
                                        panel=self.spanel)
        self.dpanel.add_widget(self.range_opt)

        self.cbarnum_opt = SettingNumeric(title='Colorbar Numbers',
                                          desc='Number of data points to indicate on the colorbar',
                                          key='cbar_num',
                                          section='display',
                                          panel=self.spanel)
        self.dpanel.add_widget(self.cbarnum_opt)

        self.asym_width_opt = SettingNumeric(title='Asymmetry Window Width',
                                             desc='Width of integration window, in km/s',
                                             key='asym_width',
                                             section='display',
                                             panel=self.spanel)
        self.dpanel.add_widget(self.asym_width_opt)

        self.asym_sep_opt = SettingNumeric(title='Asymmetry Window Separation',
                                           desc='Separation of integration windows, in km/s',
                                           key='asym_sep',
                                           section='display',
                                           panel=self.spanel)
        self.dpanel.add_widget(self.asym_sep_opt)

        self._keyboard_open()
        Window.bind(on_resize=self._on_resize)

        #initial update
        self._on_resize(Window, Window.size[0], Window.size[1])
        self._saverangedialog = SaveRangeDialog(self, size_hint=(.8, .8), title="Save Range")

        self.initialized = True

    def _settings_change(self, section, key, value):
        '''
        Called on setting panel change, updates values in renderer config
        '''
        self._keyboard_open()
        if key == 'opacity':
            self.rend_opacity = (value == '1')
        elif key in ('snap', 'nlamb'):
            setattr(self, key, int(value))
        elif key == 'channel':
            self.channel = self.channellist.index(value)
        elif key == 'rendermode':
            self.rendermode = value
        elif key in ('rendermode', 'altitude', 'azimuth', 'distance_per_pixel', 'stepsize',
                     'log_offset', 'cbar_num', 'asym_width', 'asym_sep', 'noise_snr'):
            setattr(self, key, float(value))
        else:
            return
        if section == 'renderer':
            self.update()
        else:
            self.update_display()

    def _keyboard_open(self):
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        '''
        Does stuff on some keypresses
        '''
        if keycode[1] == 'w':  # view up
            self.altitude += 2
        elif keycode[1] == 's':  # view down
            self.altitude -= 2
        elif keycode[1] == 'a':  # view left
            self.azimuth -= 2
        elif keycode[1] == 'd':  # view right
            self.azimuth += 2
        elif keycode[1] == 'j':  # zoom in
            self.distance_per_pixel *= 0.95
        elif keycode[1] == 'k':  # zoom out
            self.distance_per_pixel /= 0.95
        elif keycode[1] == 'u':  # decrease contrast, increasing dyn range
            self.log_offset += 0.4
            self.update_display()  # don't rerender, just update display
            return
        elif keycode[1] == 'i':  # increase contrast
            if self.log_offset > 0:
                self.log_offset -= 0.4
            self.update_display()
            return
        elif keycode[1] == 'up':  # shift view up
            self.y_pixel_offset += 5
        elif keycode[1] == 'down':  # shift view down
            self.y_pixel_offset -= 5
        elif keycode[1] == 'left':  # shift view left
            self.x_pixel_offset -= 5
        elif keycode[1] == 'right':  # shift view right
            self.x_pixel_offset += 5
        elif keycode[1] == 'c':
            self.x_pixel_offset = self.y_pixel_offset = 0
        elif keycode[1] == ',':  # decreases stepsize, increasing resolution
            self.stepsize *= 0.8
        elif keycode[1] == '.':  # increases stepsize, decreasing resolution
            self.stepsize /= 0.8
        elif keycode[1] == '[':  # go back 1 snap
            self.snap -= 1
        elif keycode[1] == ']':  # go forward 1 snap
            self.snap += 1
        elif keycode[1] == 'o':  # toggle opacity
            self.rend_opacity = not self.rend_opacity
        else:
            return

        self.alt_opt.value = str(self.altitude)
        self.azi_opt.value = str(self.azimuth)
        self.range_opt.value = str(self.log_offset)
        self.dpp_opt.value = str(round(self.distance_per_pixel, 6))
        self.stp_opt.value = str(round(self.stepsize, 6))
        self.opa_opt.value = '1' if self.rend_opacity else '0'
        self.snap_opt.value = str(self.rend.snap)
        self.update()

    def _on_resize(self, window, width, height):
        '''
        Rerenders, resizes objects on window resize
        '''
        self.rend.projection_x_size, self.rend.projection_y_size = width, height
        self.s.size = (self.s.size[0], height)
        self.cbsize = (self.cbsize[0], height - 100)
        self.update()

    def update(self, updatedisplay=True):
        '''
        Rerenders stuff and caches it, then updates display if specified
        '''
        if not self.initialized:
            return
        # limit some values
        self.azimuth = self.azimuth % 360
        self.altitude = sorted((-90, self.altitude, 90))[1]
        self.snap = sorted(self.rend.snap_range + (self.snap,))[1]

        # set values in renderer, and render
        self.rend.distance_per_pixel = self.distance_per_pixel
        self.rend.stepsize = self.stepsize
        self.rend.y_pixel_offset = self.y_pixel_offset
        self.rend.x_pixel_offset = self.x_pixel_offset
        self.rend.set_snap(self.snap)

        # render appropriate data, cache it
        if self.rendermode == Mode.intensity:
            data, _ = self.get_i_render()
            self.raw_spectra = None
            self.raw_data = data
        else:
            data, dfreqs, ny0, _ = self.get_il_render()
            self.raw_spectra = (noisify_spectra(data, self.noise_snr), dfreqs, ny0)
            self.raw_data = None
            self.spect_analyzer.set_data(*self.raw_spectra)

        if updatedisplay:
            self.update_display()

    def update_display(self):
        '''
        Rejiggers display objects if no rerendering is required
        '''
        if self.rendermode == Mode.intensity:
            self.unittxt.text = 'Intensity: erg s[sup]-1[/sup] cm[sup]-2[/sup] sr[sup]-1[/sup]'
        elif self.rendermode == Mode.doppler_shift:
            self.raw_data = self.spect_analyzer.quad_regc()
            self.raw_data *= -CC / 1e3 / self.spect_analyzer.center_freq  # convert to km/s
            self.unittxt.text = 'Doppler shift: km/s'
        elif self.rendermode == Mode.width:
            self.raw_data = self.spect_analyzer.fwhm()
            self.raw_data *= CC / 1e3 / self.spect_analyzer.center_freq  # convert to km/s
            self.unittxt.text = 'Line width at half max: km/s'
        elif self.rendermode == Mode.asym:
            self.raw_data = self.spect_analyzer.split_integral_vel(self.asym_sep, self.asym_width, 2)
            self.raw_data = self.raw_data[..., 1] - self.raw_data[..., 0]
            self.unittxt.text = 'Intensity: erg s[sup]-1[/sup] cm[sup]-2[/sup] sr[sup]-1[/sup]'

        bounds = (np.nanmin(self.raw_data), np.nanmax(self.raw_data))
        if bounds[0] >= 0:  # use symlog-based approach starting from 0
            SCALAR_MAP.set_norm(colors.SymLogNorm(bounds[1] * 0.1 ** self.log_offset))
            SCALAR_MAP.set_cmap(cm.bone)
            SCALAR_MAP.set_clim(0, bounds[1])
        else:  # use symlog approach
            b2 = max((abs(bounds[0]), bounds[1]))
            SCALAR_MAP.set_cmap(SYM_MAP)
            SCALAR_MAP.set_norm(colors.SymLogNorm(b2 * 0.1 ** self.log_offset))
            SCALAR_MAP.set_clim(-b2, b2)

        data = SCALAR_MAP.to_rgba(self.raw_data) * 255

        # update display buffer
        self.buffer_array[:data.shape[0], :data.shape[1]] = data
        self.texture.blit_buffer(self.buffer_array.tostring(), colorfmt='rgba')

        # colorbar text generation
        self.cbtxt.text = '\n' + '\n'.join(('%.3e' % val for val in
                                            reversed(SCALAR_MAP.norm.inverse(np.linspace(0, 1, self.cbar_num)))))
        self.cbtxt.line_height = self.cbsize[1] / (self.cbar_num - 1) / (self.cbtxt.font_size + 3)
        self.cbtxt.center_y = 50 + self.cbsize[1] / 2 + self.cbtxt.font_size / 2

        # colorbar generation
        SCALAR_MAP.set_norm(colors.NoNorm())
        cb_raw = np.empty(self.cbsize[::-1])
        cb_raw[:] = np.expand_dims(np.linspace(0, 1, self.cbsize[1]), 1)
        cb_data = SCALAR_MAP.to_rgba(cb_raw) * 255
        self.cbtex.blit_buffer(cb_data.astype('uint8').tostring(), size=self.cbsize, colorfmt='rgba')

    def save_image(self):
        output_name = tkFileDialog.asksaveasfilename(title='Image Array Filename')
        if not output_name:
            return
        self.rend.save_irender(output_name, self.raw_data)

    def save_spectra(self):
        output_name = tkFileDialog.asksaveasfilename(title='Spectra Array Filename')
        if not output_name:
            return
        if self.raw_spectra is None:
            self.rend.distance_per_pixel = self.distance_per_pixel
            self.rend.stepsize = self.stepsize
            self.rend.y_pixel_offset = self.y_pixel_offset
            self.rend.x_pixel_offset = self.x_pixel_offset
            data, dfreqs, ny0, _ = self.get_il_render()
            self.raw_spectra = (noisify_spectra(data, self.noise_snr), dfreqs, ny0)
        self.rend.save_ilrender(output_name, self.raw_spectra)

    def save_range(self):
        self._saverangedialog.rend_choice = None
        self._saverangedialog.open()

    def _renderrangefromdialog(self, srd, choice):
        snap_bounds = sorted((int(srd.slider_snapmin.value), int(srd.slider_snapmax.value)))
        snap_skip = int(srd.slider_snapskip.value)
        snap_range = range(snap_bounds[0], snap_bounds[1], snap_skip)
        channellist = self.channellist
        channel_ids = [channellist.index(lib.text) for lib in srd.channelselect.adapter.selection]
        save_loc = srd.savefilename.text
        save_loct = Template(save_loc)
        if len(snap_range) > 1 and '${num}' not in save_loc or len(channel_ids) > 1 and '${chan}' not in save_loc:
            ed = ErrorDialog()
            ed.errortext = 'Missing "${num}" or "${chan}" in file descriptor'
            ed.open()
            return

        orig_mode, orig_snap, orig_channel = self.rendermode, self.snap, self.channel

        # if spectra is chosen, choose mode that caches spectra
        if choice == 'il':
            self.rendermode = Mode.doppler_shift

        for snap in snap_range:
            self.snap = snap
            for channel_id in channel_ids:
                self.channel = channel_id
                save_file = save_loct.substitute(num=str(snap), chan=channellist[channel_id])

                self.update(False)

                if choice == 'il':
                    self.rend.save_ilrender(save_file, self.raw_spectra)
                elif choice == 'i':
                    # process spectra into raw data if necessary
                    if self.rendermode == Mode.doppler_shift:
                        self.raw_data = self.spect_analyzer.quad_regc()
                        self.raw_data *= -CC / 1e3 / self.spect_analyzer.center_freq  # convert to km/s
                    elif self.rendermode == Mode.width:
                        self.raw_data = self.spect_analyzer.fwhm()
                        self.raw_data *= CC / 1e3 / self.spect_analyzer.center_freq  # convert to km/s
                    elif self.rendermode == Mode.asym:
                        self.raw_data = self.spect_analyzer.split_integral_vel(self.asym_sep, self.asym_width, 2)
                        self.raw_data = self.raw_data[..., 1] - self.raw_data[..., 0]
                    self.rend.save_irender(save_file, self.raw_data)

        srd.dismiss()
        self.mode, self.snap, self.channel = orig_mode, orig_snap, orig_channel
        self.raw_data = self.raw_spectra = None
        self.update()

    def get_i_render(self):
        return self.rend.i_render(self.channel, self.azimuth, -self.altitude,
                                  opacity=self.rend_opacity, verbose=False)

    def get_il_render(self):
        return self.rend.il_render(self.channel, self.azimuth, -self.altitude, nlamb=self.nlamb,
                                   opacity=self.rend_opacity, verbose=False)
Exemple #19
0
class App(KivyApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # UI
        self.title: str = 'Aiventure'
        self.sm: Optional[ScreenManager] = None
        self.screens: Dict[str, ClassVar] = {}
        # AI
        self.ai: Optional[AI] = None
        self.adventure: Optional[Adventure] = None
        # Threading
        self.threads: Dict[str, Thread] = {}
        # Modules
        self.loaded_modules: Dict[str, str] = {}
        self.input_filters: List[Callable[[str], str]] = []
        self.output_filters: List[Callable[[str], str]] = []
        self.display_filter: Optional[Callable[[List[str]], str]] = None

    def build(self) -> ScreenManager:
        """
        """
        self.init_mods()
        self.init_ui()
        return self.sm

    def build_config(self, _) -> None:
        """
        """
        self.config = ConfigParser()
        self.config.read('config.ini')
        self.config.setdefaults('general', {
            'userdir': 'user',
            'autosave': True
        })
        self.config.setdefaults(
            'ai', {
                'timeout': 20.0,
                'memory': 20,
                'max_length': 60,
                'beam_searches': 1,
                'temperature': 0.8,
                'top_k': 40,
                'top_p': 0.9,
                'repetition_penalty': 1.1
            })
        self.config.setdefaults(
            'modules', {
                'input_filters': 'aiventure:filters',
                'output_filters': 'aiventure:filters',
                'display_filter': 'aiventure:filters'
            })
        self.config.write()

    def init_mods(self) -> None:
        """
        Initializes the game's module system and loads mods based on the current configuration.
        """
        sys.path.append(self.config.get('general', 'userdir'))

        for f in self.config.get('modules', 'input_filters').split(','):
            domain, module = f.split(':')
            Logger.info(f'Modules: Loading {f}.filter_input')
            self.input_filters += [
                self.load_submodule(domain, module, 'filter_input')
            ]

        for f in self.config.get('modules', 'output_filters').split(','):
            domain, module = f.split(':')
            Logger.info(f'Modules: Loading {f}.filter_output')
            self.output_filters += [
                self.load_submodule(domain, module, 'filter_output')
            ]

        domain, module = self.config.get('modules',
                                         'display_filter').split(':')
        Logger.info(f'Modules: Loading {f}.filter_display')
        self.display_filter = self.load_submodule(domain, module,
                                                  'filter_display')

    def init_ui(self) -> None:
        """
        Initializes the screen manager, loads all screen kivy files and their associated python modules.
        """
        self.sm = ScreenManager()
        self.screens = {'menu': MenuScreen, 'play': PlayScreen}
        for n, s in self.screens.items():
            Builder.load_file(f'aiventure/client/uix/{n}.kv')
            self.sm.add_widget(s(name=n))
        self.sm.current = 'menu'

    def get_user_path(self, *args: str) -> str:
        """
        Retrieves a path relative to the current user directory.

        :param args: The subdirectories / filenames in the user directory.
        :return: A path in the current user directory.
        """
        return os.path.join(self.config.get('general', 'userdir'), *args)

    def get_model_path(self, model: str) -> str:
        """
        Gets the path to the currently selected (but not necessarily loaded) AI model.

        :param model: The model within the models subdirectory.
        :return: The current selected model path.
        """
        return self.get_user_path('models', model)

    def get_valid_models(self) -> List[str]:
        """
        :return: A list of valid model names, inside {userdir}/models
        """
        return [
            m.name for m in os.scandir(self.get_user_path('models'))
            if is_model_valid(m.path)
        ]

    def get_module_path(self, domain: str, module: str) -> str:
        return self.get_user_path('modules', domain, f'{module}.py')

    def load_module(self, domain: str, module: str) -> Any:
        """
        Loads a module and returns it (if it hasn't been loaded already).

        :param domain: The module domain.
        :param module: The module to load from the given domain.
        :return: The loaded module.
        """
        k = f'{domain}:{module}'
        v = self.loaded_modules.get(k)
        if v is None:
            v = importlib.import_module(f'.{module}', f'modules.{domain}')
            self.loaded_modules[k] = v
        return v

    def load_submodule(self, domain: str, module: str, submodule: str) -> str:
        """
        Loads a submodule (a method, class, or variable from a given module).

        :param domain: The module domain.
        :param module: The module to load from the given domain.
        :param submodule: The submodule to load from the given module.
        :return: The loaded submodule.
        """
        m = self.load_module(domain, module)
        return getattr(m, submodule)

    # SAVING AND LOADING

    def save_adventure(self) -> None:
        """
        Saves the current adventure.
        """
        savefile = get_save_name(self.adventure.name)
        with open(self.get_user_path('adventures', f'{savefile}.json'),
                  'w') as json_file:
            json.dump(self.adventure.to_dict(), json_file, indent=4)

    def load_adventure(self) -> None:
        """
        Loads the current adventure.
        """
        savefile = get_save_name(self.adventure.name)
        with open(self.get_user_path('adventures', f'{savefile}.json'),
                  'r') as json_file:
            self.adventure.from_dict(json.load(json_file))
Exemple #20
0
def test_configparser_setdefaults():
    """Test the setdefaults method works as expected."""
    config = ConfigParser()
    config.setdefaults('section', {'test': '1'})

    assert config.get('section', 'test') == '1'