예제 #1
0
    def __init__(self):
        super().__init__()
        self.corpus = None
        self.last_config = None  # to avoid reruns with the same params
        self.strings_attrs = []
        self.profiler = TweetProfiler(on_server_down=self.Error.server_down)

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Auto commit
        buttons_layout = QHBoxLayout()
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False))
        self.controlArea.layout().addLayout(buttons_layout)
예제 #2
0
    def __init__(self):
        OWWidget.__init__(self)
        ConcurrentWidgetMixin.__init__(self)
        self.corpus = None
        self.last_config = None     # to avoid reruns with the same params
        self.strings_attrs = []
        self.profiler = TweetProfiler(on_server_down=self.Error.server_down)

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Auto commit
        buttons_layout = QHBoxLayout()
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False)
        )
        self.controlArea.layout().addLayout(buttons_layout)

        self.cancel_button = QPushButton(
            'Cancel',
            icon=self.style()
            .standardIcon(QStyle.SP_DialogCancelButton))

        self.cancel_button.clicked.connect(self.cancel)

        hbox = gui.hBox(self.controlArea)
        hbox.layout().addWidget(self.cancel_button)
        self.cancel_button.setDisabled(True)
예제 #3
0
class TestErrorsRaising(unittest.TestCase):
    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def setUp(self):
        self.profiler = TweetProfiler()

    @patch('requests.get',
           Mock(side_effect=requests.exceptions.ConnectionError))
    def test_get_server_address_connection_error(self):
        address = self.profiler.get_server_address()
        self.assertIsNone(address)

    @patch(CHECK_ALIVE, Mock(return_value=False))
    def test_get_server_address_server_down(self):
        address = self.profiler.get_server_address()
        self.assertIsNone(address)

    @patch('requests.head', Mock(return_value=response_mock))
    def test_server_alive(self):
        self.assertTrue(TweetProfiler.check_server_alive(''))

    @patch('requests.head',
           Mock(side_effect=requests.exceptions.ConnectionError))
    def test_server_raise_error(self):
        self.assertFalse(TweetProfiler.check_server_alive(''))

    @patch(CHECK_ALIVE, Mock(return_value=False))
    def test_assure_server_and_tokens_server_down(self):
        self.profiler.on_server_down = Mock()
        r = self.profiler.assure_server()
        self.assertFalse(r)
        self.assertEqual(self.profiler.on_server_down.call_count, 1)

    @patch(SERVER_CALL, MockServerCall())
    def test_assure_server_and_tokens_get_server(self):
        self.profiler.server = None
        r = self.profiler.assure_server()
        self.assertTrue(r)

    def test_server_call_server_missing(self):
        self.profiler.server = None
        r = self.profiler.server_call('', {})
        self.assertIsNone(r)

    @patch('requests.post', Mock(return_value=response_mock))
    def test_server_call_server_ok(self):
        r = self.profiler.server_call('', {})
        self.assertEqual(r, {})

    @patch('requests.post',
           Mock(side_effect=requests.exceptions.RequestException))
    def test_server_call_server_ok(self):
        self.profiler.on_server_down = Mock()
        r = self.profiler.server_call('', {})
        self.assertIsNone(r)
        self.assertEqual(self.profiler.on_server_down.call_count, 1)
예제 #4
0
    def __init__(self):
        super().__init__()
        self.corpus = None
        self.strings_attrs = []
        self.profiler = TweetProfiler(
            token=self.token,
            on_server_down=self.Error.server_down,
            on_invalid_token=self.Error.invalid_token,
            on_too_little_credit=self.Error.no_credit,
        )

        # Info box
        self.n_documents = ''
        self.credit = 0
        box = gui.widgetBox(self.controlArea, "Info")
        gui.label(box, self, 'Documents: %(n_documents)s')
        gui.label(box, self, 'Credits: %(credit)s')

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Server token
        box = gui.vBox(self.controlArea, 'Server Token')
        gui.lineEdit(box,
                     self,
                     'token',
                     callback=self.token_changed,
                     controlWidth=300)
        gui.button(box, self, 'Get Token', callback=self.get_new_token)

        # Auto commit
        buttons_layout = QtGui.QHBoxLayout()
        buttons_layout.addWidget(self.report_button)
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False))
        self.controlArea.layout().addLayout(buttons_layout)

        self.refresh_token_info()
예제 #5
0
class TestErrorsRaising(unittest.TestCase):
    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def setUp(self):
        self.profiler = TweetProfiler()

    @patch('requests.get', Mock(side_effect=requests.exceptions.ConnectionError))
    def test_get_server_address_connection_error(self):
        address = self.profiler.get_server_address()
        self.assertIsNone(address)

    @patch(CHECK_ALIVE, Mock(return_value=False))
    def test_get_server_address_server_down(self):
        address = self.profiler.get_server_address()
        self.assertIsNone(address)

    @patch('requests.head', Mock(return_value=response_mock))
    def test_server_alive(self):
        self.assertTrue(TweetProfiler.check_server_alive(''))

    @patch('requests.head', Mock(side_effect=requests.exceptions.ConnectionError))
    def test_server_raise_error(self):
        self.assertFalse(TweetProfiler.check_server_alive(''))

    @patch(CHECK_ALIVE, Mock(return_value=False))
    def test_assure_server_and_tokens_server_down(self):
        self.profiler.on_server_down = Mock()
        r = self.profiler.assure_server()
        self.assertFalse(r)
        self.assertEqual(self.profiler.on_server_down.call_count, 1)

    @patch(SERVER_CALL, MockServerCall())
    def test_assure_server_and_tokens_get_server(self):
        self.profiler.server = None
        r = self.profiler.assure_server()
        self.assertTrue(r)

    def test_server_call_server_missing(self):
        self.profiler.server = None
        r = self.profiler.server_call('', {})
        self.assertIsNone(r)

    @patch('requests.post', Mock(return_value=response_mock))
    def test_server_call_server_ok(self):
        r = self.profiler.server_call('', {})
        self.assertEqual(r, {})

    @patch('requests.post', Mock(side_effect=requests.exceptions.RequestException))
    def test_server_call_server_ok(self):
        self.profiler.on_server_down = Mock()
        r = self.profiler.server_call('', {})
        self.assertIsNone(r)
        self.assertEqual(self.profiler.on_server_down.call_count, 1)
예제 #6
0
    def __init__(self):
        super().__init__()
        self.corpus = None
        self.last_config = None     # to avoid reruns with the same params
        self.strings_attrs = []
        self.profiler = TweetProfiler(on_server_down=self.Error.server_down)

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Auto commit
        buttons_layout = QHBoxLayout()
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False)
        )
        self.controlArea.layout().addLayout(buttons_layout)
예제 #7
0
    def __init__(self):
        super().__init__()
        self.corpus = None
        self.strings_attrs = []
        self.profiler = TweetProfiler(
            token=self.token,
            on_server_down=self.Error.server_down,
            on_invalid_token=self.Error.invalid_token,
            on_too_little_credit=self.Error.no_credit,
        )

        # Info box
        self.n_documents = ''
        self.credit = 0
        box = gui.widgetBox(self.controlArea, "Info")
        gui.label(box, self, 'Documents: %(n_documents)s')
        gui.label(box, self, 'Credits: %(credit)s')

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Server token
        box = gui.vBox(self.controlArea, 'Server Token')
        gui.lineEdit(box, self, 'token', callback=self.token_changed,
                     controlWidth=300)
        gui.button(box, self, 'Get Token', callback=self.get_new_token)

        # Auto commit
        buttons_layout = QtGui.QHBoxLayout()
        buttons_layout.addWidget(self.report_button)
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False)
        )
        self.controlArea.layout().addLayout(buttons_layout)

        self.refresh_token_info()
예제 #8
0
class TestTweetProfiler(unittest.TestCase):
    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def setUp(self):
        self.data = Corpus.from_file('election-tweets-2016.tab')[:100]
        self.profiler = TweetProfiler()

    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_get_server_address(self):
        server = self.profiler.get_server_address()
        self.assertTrue(server.startswith('http'))

    @patch(SERVER_CALL, MockServerCall())
    def test_get_configuration(self):
        self.assertEqual(self.profiler.model_names, MODELS)
        self.assertEqual(self.profiler.output_modes, MODES)

    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_transform_embeddings(self):
        advance_call_mock = Mock()
        text_var = self.data.domain.metas[1]
        corp = self.profiler.transform(self.data,
                                       text_var,
                                       'model-mc',
                                       'Embeddings',
                                       on_advance=advance_call_mock)
        self.assertIsInstance(corp, Corpus)
        self.assertEqual(advance_call_mock.call_count, 2)
        self.assertEqual(
            len(corp.domain.attributes) - len(self.data.domain.attributes),
            EMBEDDINGS_NUM)
        self.assertEqual(corp.X.shape[1] - self.data.X.shape[1],
                         EMBEDDINGS_NUM)
        self.assertEqual(np.sum(corp.X[:, -EMBEDDINGS_NUM]), 0)

    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_transform_probabilities_and_ml_classes(self):
        text_var = self.data.domain.metas[1]
        for mode in ['Probabilities', 'Classes']:
            corp = self.profiler.transform(self.data, text_var, 'model-ml',
                                           mode)
            self.assertIsInstance(corp, Corpus)
            self.assertEqual(
                len(corp.domain.attributes) - len(self.data.domain.attributes),
                len(PROFILE_CLASSES))
            self.assertEqual(corp.X.shape[1] - self.data.X.shape[1],
                             len(PROFILE_CLASSES))
            self.assertEqual(np.sum(corp.X[:, -len(PROFILE_CLASSES)]), 0)

    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_transform_mc_classes(self):
        text_var = self.data.domain.metas[1]
        corp = self.profiler.transform(self.data, text_var, 'model-mc',
                                       'Classes')
        self.assertIsInstance(corp, Corpus)
        self.assertEqual(
            len(corp.domain.attributes) - len(self.data.domain.attributes), 1)
        self.assertEqual(corp.X.shape[1] - self.data.X.shape[1], 1)
        self.assertEqual(np.sum(corp.X[:, -1]), 0)

    @patch(CHECK_ALIVE, Mock(return_value=False))
    def test_transform_probabilities(self):
        text_var = self.data.domain.metas[1]
        corp = self.profiler.transform(self.data, text_var, MODELS[0],
                                       'Classes')
        self.assertIsNone(corp)

    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_transform_empty_corpus(self):
        text_var = self.data.domain.metas[1]
        corp = self.profiler.transform(self.data[:0], text_var, 'model-mc',
                                       'Classes')
        self.assertIsNone(corp)

    @patch(SERVER_CALL, MockServerCallSuddenlyUnavailable())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_transform_server_call_error(self):
        text_var = self.data.domain.metas[1]
        corp = self.profiler.transform(self.data, text_var, 'model-mc',
                                       'Classes')
        self.assertIsNone(corp)
예제 #9
0
class OWTweetProfiler(OWWidget):
    name = "Tweet Profiler"
    description = "Detect Ekman's, Plutchik's or Profile of Mood States's " \
                  "emotions in tweets."
    icon = "icons/TweetProfiler.svg"
    priority = 330
    keywords = ["Twitter"]

    class Inputs:
        corpus = Input("Corpus", Corpus)

    class Outputs:
        corpus = Output("Corpus", Corpus)

    want_main_area = False
    resizing_enabled = False

    model_name = Setting('')
    output_mode = Setting('')
    tweet_attr = Setting(0)
    auto_commit = Setting(True)

    class Error(OWWidget.Error):
        server_down = Msg('Our servers are not responding. '
                          'Please try again later.')

    def __init__(self):
        super().__init__()
        self.corpus = None
        self.last_config = None     # to avoid reruns with the same params
        self.strings_attrs = []
        self.profiler = TweetProfiler(on_server_down=self.Error.server_down)

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Auto commit
        buttons_layout = QHBoxLayout()
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False)
        )
        self.controlArea.layout().addLayout(buttons_layout)

    def generate_grid_layout(self):
        box = QGroupBox(title='Options')

        layout = QGridLayout()
        layout.setSpacing(10)
        row = 0

        self.tweet_attr_combo = gui.comboBox(None, self, 'tweet_attr',
                                             callback=self.apply)
        layout.addWidget(QLabel('Attribute:'))
        layout.addWidget(self.tweet_attr_combo, row, 1)

        row += 1
        self.model_name_combo = gui.comboBox(None, self, 'model_name',
                                             items=self.profiler.model_names,
                                             sendSelectedValue=True,
                                             callback=self.apply)
        if self.profiler.model_names:
            self.model_name = self.profiler.model_names[0]  # select 0th
        layout.addWidget(QLabel('Emotions:'))
        layout.addWidget(self.model_name_combo, row, 1)

        row += 1
        self.output_mode_combo = gui.comboBox(None, self, 'output_mode',
                                              items=self.profiler.output_modes,
                                              sendSelectedValue=True,
                                              callback=self.apply)
        if self.profiler.output_modes:
            self.output_mode = self.profiler.output_modes[0]    # select 0th
        layout.addWidget(QLabel('Output:'))
        layout.addWidget(self.output_mode_combo, row, 1)

        box.setLayout(layout)
        return box

    @Inputs.corpus
    def set_corpus(self, corpus):
        self.corpus = corpus

        if corpus is not None:
            self.strings_attrs = [a for a in self.corpus.domain.metas
                                  if isinstance(a, StringVariable)]
            self.tweet_attr_combo.setModel(VariableListModel(self.strings_attrs))
            self.tweet_attr_combo.currentIndexChanged.emit(self.tweet_attr)

            # select the first feature from 'text_features' if present
            ind = [self.strings_attrs.index(tf)
                   for tf in corpus.text_features
                   if tf in self.strings_attrs]
            if ind:
                self.tweet_attr = ind[0]

        self.commit()

    def apply(self):
        if self.last_config != self._get_config():
            self.commit()

    def _get_config(self):
        return self.tweet_attr, self.model_name, self.output_mode

    def commit(self):
        self.Error.clear()

        if self.corpus is not None:
            self.last_config = self._get_config()
            with self.progressBar(iterations=len(self.corpus)) as pb:
                out = self.profiler.transform(
                    self.corpus, self.strings_attrs[self.tweet_attr],
                    self.model_name, self.output_mode,
                    on_advance=pb.advance)
            self.Outputs.corpus.send(out)
        else:
            self.Outputs.corpus.send(None)

    def send_report(self):
        self.report_items([
            ('Attribute', self.strings_attrs[self.tweet_attr]
                if len(self.strings_attrs) > self.tweet_attr else ''),
            ('Emotions', self.model_name),
            ('Output', self.output_mode),
        ])
예제 #10
0
class OWTweetProfiler(OWWidget):
    name = "Tweet Profiler"
    description = "Detect Ekman's, Plutchik's or Profile of Mood States's " \
                  "emotions in tweets."
    icon = "icons/TweetProfiler.svg"
    priority = 46

    inputs = [(IO.CORPUS, Corpus, 'set_corpus')]
    outputs = [(IO.CORPUS, Corpus)]

    want_main_area = False
    resizing_enabled = False

    token = Setting('')
    model_name = Setting('')
    output_mode = Setting('')
    tweet_attr = Setting(0)
    auto_commit = Setting(True)

    class Error(OWWidget.Error):
        server_down = Msg('Our servers are not responding. '
                          'Please try again later.')
        invalid_token = Msg('This token is invalid')
        no_credit = Msg('Too little credits for this data set')

    def __init__(self):
        super().__init__()
        self.corpus = None
        self.strings_attrs = []
        self.profiler = TweetProfiler(
            token=self.token,
            on_server_down=self.Error.server_down,
            on_invalid_token=self.Error.invalid_token,
            on_too_little_credit=self.Error.no_credit,
        )

        # Info box
        self.n_documents = ''
        self.credit = 0
        box = gui.widgetBox(self.controlArea, "Info")
        gui.label(box, self, 'Documents: %(n_documents)s')
        gui.label(box, self, 'Credits: %(credit)s')

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Server token
        box = gui.vBox(self.controlArea, 'Server Token')
        gui.lineEdit(box, self, 'token', callback=self.token_changed,
                     controlWidth=300)
        gui.button(box, self, 'Get Token', callback=self.get_new_token)

        # Auto commit
        buttons_layout = QtGui.QHBoxLayout()
        buttons_layout.addWidget(self.report_button)
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False)
        )
        self.controlArea.layout().addLayout(buttons_layout)

        self.refresh_token_info()

    def generate_grid_layout(self):
        box = QtGui.QGroupBox(title='Options')

        layout = QGridLayout()
        layout.setSpacing(10)
        row = 0

        self.tweet_attr_combo = gui.comboBox(None, self, 'tweet_attr',
                                             callback=self.apply)
        layout.addWidget(QLabel('Attribute:'))
        layout.addWidget(self.tweet_attr_combo, row, 1)

        row += 1
        self.model_name_combo = gui.comboBox(None, self, 'model_name',
                                             items=self.profiler.model_names,
                                             sendSelectedValue=True,
                                             callback=self.apply)
        if self.profiler.model_names:
            self.model_name = self.profiler.model_names[0]  # select 0th
        layout.addWidget(QLabel('Emotions:'))
        layout.addWidget(self.model_name_combo, row, 1)

        row += 1
        self.output_mode_combo = gui.comboBox(None, self, 'output_mode',
                                              items=self.profiler.output_modes,
                                              sendSelectedValue=True,
                                              callback=self.apply)
        if self.profiler.output_modes:
            self.output_mode = self.profiler.output_modes[0]    # select 0th
        layout.addWidget(QLabel('Output:'))
        layout.addWidget(self.output_mode_combo, row, 1)

        box.setLayout(layout)
        return box

    def set_corpus(self, corpus):
        self.corpus = corpus

        if corpus is not None:
            self.strings_attrs = [a for a in self.corpus.domain.metas
                                  if isinstance(a, StringVariable)]
            self.tweet_attr_combo.setModel(VariableListModel(self.strings_attrs))
            self.tweet_attr_combo.currentIndexChanged.emit(self.tweet_attr)

            # select the first feature from 'text_features' if present
            ind = [self.strings_attrs.index(tf)
                   for tf in corpus.text_features
                   if tf in self.strings_attrs]
            if ind:
                self.tweet_attr = ind[0]

            self.n_documents = len(corpus)
        self.commit()

    def apply(self):
        self.commit()

    def commit(self):
        self.Error.clear()

        if self.corpus is not None:
            with self.progressBar(iterations=len(self.corpus)) as pb:
                out = self.profiler.transform(
                    self.corpus, self.strings_attrs[self.tweet_attr],
                    self.model_name, self.output_mode,
                    on_advance=pb.advance)
            self.send(IO.CORPUS, out)
        else:
            self.send(IO.CORPUS, None)

        self.refresh_token_info()

    def get_new_token(self):
        self.Warning.clear()
        self.profiler.new_token()
        self.token = self.profiler.token
        self.refresh_token_info()
        self.commit()

    def token_changed(self):
        self.profiler.token = self.token
        self.refresh_token_info()
        self.commit()

    def refresh_token_info(self):
        self.credit = str(self.profiler.get_credit())

    def send_report(self):
        self.report_items([
            ('Documents', self.n_documents),
            ('Attribute', self.strings_attrs[self.tweet_attr]
                if len(self.strings_attrs) > self.tweet_attr else ''),
            ('Emotions', self.model_name),
            ('Output', self.output_mode),
        ])
예제 #11
0
class TestTweetProfiler(unittest.TestCase):
    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def setUp(self):
        self.data = Corpus.from_file('Election-2016-Tweets.tab')[:100]
        self.profiler = TweetProfiler()

    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_get_server_address(self):
        server = self.profiler.get_server_address()
        self.assertTrue(server.startswith('http'))

    @patch(SERVER_CALL, MockServerCall())
    def test_get_configuration(self):
        self.assertEqual(self.profiler.model_names, MODELS)
        self.assertEqual(self.profiler.output_modes, MODES)

    @patch(SERVER_CALL, MockServerCall())
    def test_get_token(self):
        self.assertIsNone(self.profiler.token)
        self.profiler.new_token()
        self.assertEqual(self.profiler.token, TOKEN)

    @patch(SERVER_CALL, MockServerCall())
    def test_is_token_valid(self):
        self.assertEqual(self.profiler.is_token_valid(), VALID)

    @patch(SERVER_CALL, MockServerCall())
    def test_get_credit(self):
        self.assertEqual(self.profiler.get_credit(), COINS)

    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_transform_embeddings(self):
        advance_call_mock = Mock()
        text_var = self.data.domain.metas[1]
        corp = self.profiler.transform(self.data, text_var,
                                       'model-mc', 'Embeddings',
                                       on_advance=advance_call_mock)
        self.assertIsInstance(corp, Corpus)
        self.assertEqual(advance_call_mock.call_count, 2)
        self.assertEqual(len(corp.domain.attributes) -
                         len(self.data.domain.attributes),
                         EMBEDDINGS_NUM)
        self.assertEqual(corp.X.shape[1] - self.data.X.shape[1],
                         EMBEDDINGS_NUM)
        self.assertEqual(np.sum(corp.X[:, -EMBEDDINGS_NUM]), 0)

    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_transform_probabilities_and_ml_classes(self):
        text_var = self.data.domain.metas[1]
        for mode in ['Probabilities', 'Classes']:
            corp = self.profiler.transform(self.data, text_var,
                                           'model-ml', mode)
            self.assertIsInstance(corp, Corpus)
            self.assertEqual(len(corp.domain.attributes) -
                             len(self.data.domain.attributes),
                             len(PROFILE_CLASSES))
            self.assertEqual(corp.X.shape[1] - self.data.X.shape[1],
                             len(PROFILE_CLASSES))
            self.assertEqual(np.sum(corp.X[:, -len(PROFILE_CLASSES)]), 0)

    @patch(SERVER_CALL, MockServerCall())
    @patch(CHECK_ALIVE, Mock(return_value=True))
    def test_transform_mc_classes(self):
        text_var = self.data.domain.metas[1]
        corp = self.profiler.transform(self.data, text_var,
                                       'model-mc', 'Classes')
        self.assertIsInstance(corp, Corpus)
        self.assertEqual(len(corp.domain.attributes) -
                         len(self.data.domain.attributes),
                         1)
        self.assertEqual(corp.X.shape[1] - self.data.X.shape[1], 1)
        self.assertEqual(np.sum(corp.X[:, -1]), 0)

    @patch(CHECK_ALIVE, Mock(return_value=False))
    def test_transform_probabilities(self):
        text_var = self.data.domain.metas[1]
        corp = self.profiler.transform(self.data, text_var,
                                       MODELS[0], 'Classes')
        self.assertIs(corp, self.data)
예제 #12
0
 def setUp(self):
     self.data = Corpus.from_file('Election-2016-Tweets.tab')[:100]
     self.profiler = TweetProfiler()
예제 #13
0
 def test_server_alive(self):
     self.assertTrue(TweetProfiler.check_server_alive(''))
예제 #14
0
 def test_server_raise_error(self):
     self.assertFalse(TweetProfiler.check_server_alive(''))
예제 #15
0
class OWTweetProfiler(OWWidget):
    name = "Tweet Profiler"
    description = "Detect Ekman's, Plutchik's or Profile of Mood States's " \
                  "emotions in tweets."
    icon = "icons/TweetProfiler.svg"
    priority = 330

    class Inputs:
        corpus = Input("Corpus", Corpus)

    class Outputs:
        corpus = Output("Corpus", Corpus)

    want_main_area = False
    resizing_enabled = False

    model_name = Setting('')
    output_mode = Setting('')
    tweet_attr = Setting(0)
    auto_commit = Setting(True)

    class Error(OWWidget.Error):
        server_down = Msg('Our servers are not responding. '
                          'Please try again later.')

    def __init__(self):
        super().__init__()
        self.corpus = None
        self.last_config = None     # to avoid reruns with the same params
        self.strings_attrs = []
        self.profiler = TweetProfiler(on_server_down=self.Error.server_down)

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Auto commit
        buttons_layout = QHBoxLayout()
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False)
        )
        self.controlArea.layout().addLayout(buttons_layout)

    def generate_grid_layout(self):
        box = QGroupBox(title='Options')

        layout = QGridLayout()
        layout.setSpacing(10)
        row = 0

        self.tweet_attr_combo = gui.comboBox(None, self, 'tweet_attr',
                                             callback=self.apply)
        layout.addWidget(QLabel('Attribute:'))
        layout.addWidget(self.tweet_attr_combo, row, 1)

        row += 1
        self.model_name_combo = gui.comboBox(None, self, 'model_name',
                                             items=self.profiler.model_names,
                                             sendSelectedValue=True,
                                             callback=self.apply)
        if self.profiler.model_names:
            self.model_name = self.profiler.model_names[0]  # select 0th
        layout.addWidget(QLabel('Emotions:'))
        layout.addWidget(self.model_name_combo, row, 1)

        row += 1
        self.output_mode_combo = gui.comboBox(None, self, 'output_mode',
                                              items=self.profiler.output_modes,
                                              sendSelectedValue=True,
                                              callback=self.apply)
        if self.profiler.output_modes:
            self.output_mode = self.profiler.output_modes[0]    # select 0th
        layout.addWidget(QLabel('Output:'))
        layout.addWidget(self.output_mode_combo, row, 1)

        box.setLayout(layout)
        return box

    @Inputs.corpus
    def set_corpus(self, corpus):
        self.corpus = corpus

        if corpus is not None:
            self.strings_attrs = [a for a in self.corpus.domain.metas
                                  if isinstance(a, StringVariable)]
            self.tweet_attr_combo.setModel(VariableListModel(self.strings_attrs))
            self.tweet_attr_combo.currentIndexChanged.emit(self.tweet_attr)

            # select the first feature from 'text_features' if present
            ind = [self.strings_attrs.index(tf)
                   for tf in corpus.text_features
                   if tf in self.strings_attrs]
            if ind:
                self.tweet_attr = ind[0]

        self.commit()

    def apply(self):
        if self.last_config != self._get_config():
            self.commit()

    def _get_config(self):
        return self.tweet_attr, self.model_name, self.output_mode

    def commit(self):
        self.Error.clear()

        if self.corpus is not None:
            self.last_config = self._get_config()
            with self.progressBar(iterations=len(self.corpus)) as pb:
                out = self.profiler.transform(
                    self.corpus, self.strings_attrs[self.tweet_attr],
                    self.model_name, self.output_mode,
                    on_advance=pb.advance)
            self.Outputs.corpus.send(out)
        else:
            self.Outputs.corpus.send(None)

    def send_report(self):
        self.report_items([
            ('Attribute', self.strings_attrs[self.tweet_attr]
                if len(self.strings_attrs) > self.tweet_attr else ''),
            ('Emotions', self.model_name),
            ('Output', self.output_mode),
        ])
예제 #16
0
 def setUp(self):
     self.profiler = TweetProfiler()
예제 #17
0
 def setUp(self):
     self.data = Corpus.from_file('election-tweets-2016.tab')[:100]
     self.profiler = TweetProfiler()
예제 #18
0
class OWTweetProfiler(OWWidget):
    name = "Tweet Profiler"
    description = "Detect Ekman's, Plutchik's or Profile of Mood States's " \
                  "emotions in tweets."
    icon = "icons/TweetProfiler.svg"
    priority = 46

    inputs = [(IO.CORPUS, Corpus, 'set_corpus')]
    outputs = [(IO.CORPUS, Corpus)]

    want_main_area = False
    resizing_enabled = False

    token = Setting('')
    model_name = Setting('')
    output_mode = Setting('')
    tweet_attr = Setting(0)
    auto_commit = Setting(True)

    class Error(OWWidget.Error):
        server_down = Msg('Our servers are not responding. '
                          'Please try again later.')
        invalid_token = Msg('This token is invalid')
        no_credit = Msg('Too little credits for this data set')

    def __init__(self):
        super().__init__()
        self.corpus = None
        self.strings_attrs = []
        self.profiler = TweetProfiler(
            token=self.token,
            on_server_down=self.Error.server_down,
            on_invalid_token=self.Error.invalid_token,
            on_too_little_credit=self.Error.no_credit,
        )

        # Info box
        self.n_documents = ''
        self.credit = 0
        box = gui.widgetBox(self.controlArea, "Info")
        gui.label(box, self, 'Documents: %(n_documents)s')
        gui.label(box, self, 'Credits: %(credit)s')

        # Settings
        self.controlArea.layout().addWidget(self.generate_grid_layout())

        # Server token
        box = gui.vBox(self.controlArea, 'Server Token')
        gui.lineEdit(box,
                     self,
                     'token',
                     callback=self.token_changed,
                     controlWidth=300)
        gui.button(box, self, 'Get Token', callback=self.get_new_token)

        # Auto commit
        buttons_layout = QtGui.QHBoxLayout()
        buttons_layout.addWidget(self.report_button)
        buttons_layout.addSpacing(15)
        buttons_layout.addWidget(
            gui.auto_commit(None, self, 'auto_commit', 'Commit', box=False))
        self.controlArea.layout().addLayout(buttons_layout)

        self.refresh_token_info()

    def generate_grid_layout(self):
        box = QtGui.QGroupBox(title='Options')

        layout = QGridLayout()
        layout.setSpacing(10)
        row = 0

        self.tweet_attr_combo = gui.comboBox(None,
                                             self,
                                             'tweet_attr',
                                             callback=self.apply)
        layout.addWidget(QLabel('Attribute:'))
        layout.addWidget(self.tweet_attr_combo, row, 1)

        row += 1
        self.model_name_combo = gui.comboBox(None,
                                             self,
                                             'model_name',
                                             items=self.profiler.model_names,
                                             sendSelectedValue=True,
                                             callback=self.apply)
        if self.profiler.model_names:
            self.model_name = self.profiler.model_names[0]  # select 0th
        layout.addWidget(QLabel('Emotions:'))
        layout.addWidget(self.model_name_combo, row, 1)

        row += 1
        self.output_mode_combo = gui.comboBox(None,
                                              self,
                                              'output_mode',
                                              items=self.profiler.output_modes,
                                              sendSelectedValue=True,
                                              callback=self.apply)
        if self.profiler.output_modes:
            self.output_mode = self.profiler.output_modes[0]  # select 0th
        layout.addWidget(QLabel('Output:'))
        layout.addWidget(self.output_mode_combo, row, 1)

        box.setLayout(layout)
        return box

    def set_corpus(self, corpus):
        self.corpus = corpus

        if corpus is not None:
            self.strings_attrs = [
                a for a in self.corpus.domain.metas
                if isinstance(a, StringVariable)
            ]
            self.tweet_attr_combo.setModel(
                VariableListModel(self.strings_attrs))
            self.tweet_attr_combo.currentIndexChanged.emit(self.tweet_attr)

            # select the first feature from 'text_features' if present
            ind = [
                self.strings_attrs.index(tf) for tf in corpus.text_features
                if tf in self.strings_attrs
            ]
            if ind:
                self.tweet_attr = ind[0]

            self.n_documents = len(corpus)
        self.commit()

    def apply(self):
        self.commit()

    def commit(self):
        self.Error.clear()

        if self.corpus is not None:
            with self.progressBar(iterations=len(self.corpus)) as pb:
                out = self.profiler.transform(
                    self.corpus,
                    self.strings_attrs[self.tweet_attr],
                    self.model_name,
                    self.output_mode,
                    on_advance=pb.advance)
            self.send(IO.CORPUS, out)
        else:
            self.send(IO.CORPUS, None)

        self.refresh_token_info()

    def get_new_token(self):
        self.Warning.clear()
        self.profiler.new_token()
        self.token = self.profiler.token
        self.refresh_token_info()
        self.commit()

    def token_changed(self):
        self.profiler.token = self.token
        self.refresh_token_info()
        self.commit()

    def refresh_token_info(self):
        self.credit = str(self.profiler.get_credit())

    def send_report(self):
        self.report_items([
            ('Documents', self.n_documents),
            ('Attribute', self.strings_attrs[self.tweet_attr]
             if len(self.strings_attrs) > self.tweet_attr else ''),
            ('Emotions', self.model_name),
            ('Output', self.output_mode),
        ])
예제 #19
0
 def test_server_raise_error(self):
     self.assertFalse(TweetProfiler.check_server_alive(''))
예제 #20
0
 def test_server_alive(self):
     self.assertTrue(TweetProfiler.check_server_alive(''))
예제 #21
0
 def setUp(self):
     self.profiler = TweetProfiler()