From b54ca8b74bca771b33829ad7dc421d665240adbe Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 6 Mar 2025 19:22:28 +0100 Subject: [PATCH 01/86] =?UTF-8?q?Cr=C3=A9ation=20d'un=20script=20test=20co?= =?UTF-8?q?ncernant=20Sci-Hubator=20afin=20de=20faire=20la=20GUI=20de=20la?= =?UTF-8?q?=20fen=C3=AAtre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/SciHubatorTest.py | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 orangecontrib/textable_prototypes/widgets/SciHubatorTest.py diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py new file mode 100644 index 00000000..79752138 --- /dev/null +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -0,0 +1,169 @@ +# Standard imports... +import re +import http +from Orange.widgets import widget, gui, settings +from Orange.widgets.utils.widgetpreview import WidgetPreview +from Orange.widgets.settings import Setting +from _textable.widgets.TextableUtils import ( + OWTextableBaseWidget, VersionedSettingsHandler, ProgressBar, + JSONMessage, InfoBox, SendButton, AdvancedSettings, + addSeparatorAfterDefaultEncodings, addAutoDetectEncoding, + normalizeCarriageReturns, getPredefinedEncodings, pluralize +) +from LTTL.Segmentation import Segmentation + +__version__ = "0.01" + + +class SciHubator(widget.OWWidget): + """An Orange widget that lets the user select an integer value""" + + # ---------------------------------------------------------------------- + # Widget's metadata... + + name = "Sci-Hubator" + description = "Export a text segmentation from a DOI or URL" + icon = "icons/lexical_hunter.svg" + priority = 10 + + # ---------------------------------------------------------------------- + # Channel definitions (NB: no input in this case)... + + inputs = [] + outputs = [('Text data', Segmentation)] + + # ---------------------------------------------------------------------- + # GUI layout parameters... + + want_main_area = False + resizing_enabled = False + + # ---------------------------------------------------------------------- + # Settings declaration and initializations (default values)... + + URLs = Setting([]) + encoding = Setting('(auto-detect)') + autoNumber = Setting(False) + autoNumberKey = Setting(u'num') + autoSend = settings.Setting(False) + importURLs = Setting(True) + importURLsKey = Setting(u'url') + lastLocation = Setting('.') + displayAdvancedSettings = Setting(False) + URL = Setting(u'') + selected_int = Setting(50) + + # Ici-dessous les variables qui n'ont pas été copiées, et conçues spécialement pour SciHubator + importAll = Setting(True) + importAbstract = Setting(False) + importText = Setting(False) + importBibliography = Setting(False) + + def __init__(self): + super().__init__() + + self.advancedSettings = AdvancedSettings( + widget=self.controlArea, + master=self, + callback=self.int_changed, + ) + self.advancedSettings.draw() + + self.infoBox = InfoBox(widget=self.controlArea) + self.sendButton = SendButton( + widget=self.controlArea, + master=self, + callback=self.int_changed, + infoBoxAttribute='infoBox', + sendIfPreCallback=self.int_changed, + ) + # ---------------------------------------------------------------------- + # User interface... + + basicURLBox = gui.widgetBox( + widget=self.controlArea, + box=u'Source', + orientation='vertical', + addSpace=False, + ) + basicURLBoxLine1 = gui.widgetBox( + widget=basicURLBox, + box=False, + orientation='horizontal', + ) + gui.lineEdit( + widget=basicURLBoxLine1, + master=self, + value='URL', + orientation='horizontal', + label=u'DOI/URL:', + labelWidth=101, + callback=self.sendButton.settingsChanged, + tooltip=( + u"The URL whose content will be imported." + ), + ) + gui.separator(widget=basicURLBox, height=3) + optionsBox = gui.widgetBox( + widget=self.controlArea, + box=u'Options', + orientation='vertical', + addSpace=False, + ) + gui.checkBox( + widget=optionsBox, + master=self, + value='importAll', + label=u'All', + labelWidth=180, + callback=self.sendButton.settingsChanged, + tooltip=( + u"Import URLs as annotations." + ), + ) + iBox = gui.indentedBox( + widget=optionsBox, + ) + gui.separator(widget=optionsBox, height=3) + gui.checkBox( + widget=iBox, + master=self, + value='importAbstract', + label=u'Abstract', + labelWidth=180, + callback=self.sendButton.settingsChanged, + tooltip=( + u"Import URLs as annotations." + ), + ) + gui.separator(widget=optionsBox, height=3) + gui.checkBox( + widget=iBox, + master=self, + value='importText', + label=u'Text', + labelWidth=180, + callback=self.sendButton.settingsChanged, + tooltip=( + u"Import URLs as annotations." + ), + ) + gui.separator(widget=optionsBox, height=3) + gui.checkBox( + widget=iBox, + master=self, + value='importBibliography', + label=u'Bibliography', + labelWidth=180, + callback=self.sendButton.settingsChanged, + tooltip=( + u"Import URLs as annotations." + ), + ) + self.sendButton.draw() + self.infoBox.draw() + self.sendButton.sendIf() + + def int_changed(self): + """Send the entered number on "Number" output""" + self.send("Text data", None) From 347209b50a4acd5dfa74d9e12d8345cb7b9f1cd8 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 6 Mar 2025 20:37:12 +0100 Subject: [PATCH 02/86] GUI des advanced settings, mais ne fonctionne pas ! Juste les graphismes. --- .../widgets/SciHubatorTest.py | 421 ++++++++++++++++++ 1 file changed, 421 insertions(+) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 79752138..396d7650 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -61,6 +61,11 @@ class SciHubator(widget.OWWidget): def __init__(self): super().__init__() + self.URLLabel = list() + self.selectedURLLabel = list() + self.newURL = u'' + self.newAnnotationKey = u'' + self.newAnnotationValue = u'' self.advancedSettings = AdvancedSettings( widget=self.controlArea, @@ -164,6 +169,422 @@ def __init__(self): self.infoBox.draw() self.sendButton.sendIf() + + self.advancedSettings.basicWidgets.append(basicURLBox) + self.advancedSettings.basicWidgetsAppendSeparator() + + # ADVANCED GUI... + + # URL box + URLBox = gui.widgetBox( + widget=self.controlArea, + box=u'Sources', + orientation='vertical', + addSpace=False, + ) + URLBoxLine1 = gui.widgetBox( + widget=URLBox, + box=False, + orientation='horizontal', + addSpace=True, + ) + self.fileListbox = gui.listBox( + widget=URLBoxLine1, + master=self, + value='selectedURLLabel', + labels='URLLabel', + callback=self.updateURLBoxButtons, + tooltip=( + u"The list of URLs whose content will be imported.\n" + u"\nIn the output segmentation, the content of each\n" + u"URL appears in the same position as in the list.\n" + u"\nColumn 1 shows the URL.\n" + u"Column 2 shows the associated annotation (if any).\n" + u"Column 3 shows the associated encoding." + ), + ) + URLBoxCol2 = gui.widgetBox( + widget=URLBoxLine1, + orientation='vertical', + ) + self.moveUpButton = gui.button( + widget=URLBoxCol2, + master=self, + label=u'Move Up', + callback=self.moveUp, + tooltip=( + u"Move the selected URL upward in the list." + ), + ) + self.moveDownButton = gui.button( + widget=URLBoxCol2, + master=self, + label=u'Move Down', + callback=self.moveDown, + tooltip=( + u"Move the selected URL downward in the list." + ), + ) + self.removeButton = gui.button( + widget=URLBoxCol2, + master=self, + label=u'Remove', + callback=self.remove, + tooltip=( + u"Remove the selected URL from the list." + ), + ) + self.clearAllButton = gui.button( + widget=URLBoxCol2, + master=self, + label=u'Clear All', + callback=self.clearAll, + tooltip=( + u"Remove all URLs from the list." + ), + ) + self.exportButton = gui.button( + widget=URLBoxCol2, + master=self, + label=u'Export List', + callback=self.exportList, + tooltip=( + u"Open a dialog for selecting a file where the URL\n" + u"list can be exported in JSON format." + ), + ) + self.importButton = gui.button( + widget=URLBoxCol2, + master=self, + label=u'Import List', + callback=self.importList, + tooltip=( + u"Open a dialog for selecting an URL list to\n" + u"import (in JSON format). URLs from this list will\n" + u"be added to those already imported." + ), + ) + URLBoxLine2 = gui.widgetBox( + widget=URLBox, + box=False, + orientation='vertical', + ) + # Add URL box + addURLBox = gui.widgetBox( + widget=URLBoxLine2, + box=True, + orientation='vertical', + addSpace=False, + ) + gui.lineEdit( + widget=addURLBox, + master=self, + value='newURL', + orientation='horizontal', + label=u'URL(s):', + labelWidth=101, + callback=self.updateGUI, + tooltip=( + u"The URL(s) that will be added to the list when\n" + u"button 'Add' is clicked.\n\n" + u"Successive URLs must be separated with ' / ' \n" + u"(space + slash + space). Their order in the list\n" + u" will be the same as in this field." + ), + ) + advOptionsBox = gui.widgetBox( + widget=self.controlArea, + box=u'Options', + orientation='vertical', + addSpace=False, + ) + gui.checkBox( + widget=advOptionsBox, + master=self, + value='importAll', + label=u'All', + labelWidth=180, + callback=self.sendButton.settingsChanged, + tooltip=( + u"Import URLs as annotations." + ), + ) + adviBox = gui.indentedBox( + widget=advOptionsBox, + ) + gui.separator(widget=advOptionsBox, height=3) + gui.checkBox( + widget=adviBox, + master=self, + value='importAbstract', + label=u'Abstract', + labelWidth=180, + callback=self.sendButton.settingsChanged, + tooltip=( + u"Import URLs as annotations." + ), + ) + gui.separator(widget=advOptionsBox, height=3) + gui.checkBox( + widget=adviBox, + master=self, + value='importText', + label=u'Text', + labelWidth=180, + callback=self.sendButton.settingsChanged, + tooltip=( + u"Import URLs as annotations." + ), + ) + gui.separator(widget=advOptionsBox, height=3) + gui.checkBox( + widget=adviBox, + master=self, + value='importBibliography', + label=u'Bibliography', + labelWidth=180, + callback=self.sendButton.settingsChanged, + tooltip=( + u"Import URLs as annotations." + ), + ) + gui.separator(widget=addURLBox, height=3) + self.addButton = gui.button( + widget=addURLBox, + master=self, + label=u'Add', + callback=self.add, + tooltip=( + u"Add the URL currently displayed in the 'URL'\n" + u"text field to the list." + ), + ) + self.advancedSettings.advancedWidgets.append(URLBox) + self.advancedSettings.advancedWidgetsAppendSeparator() + def int_changed(self): """Send the entered number on "Number" output""" self.send("Text data", None) + + def importList(self): + """Display a FileDialog and import URL list""" + filePath, _ = QFileDialog.getOpenFileName( + self, + u'Import URL List', + self.lastLocation, + u'Text files (*)' + ) + if not filePath: + return + + self.file = os.path.normpath(filePath) + self.lastLocation = os.path.dirname(filePath) + self.error() + try: + fileHandle = codecs.open(filePath, encoding='utf8') + fileContent = fileHandle.read() + fileHandle.close() + except IOError: + QMessageBox.warning( + None, + 'Textable', + "Couldn't open file.", + QMessageBox.Ok + ) + return + try: + json_data = json.loads(fileContent) + temp_URLs = list() + for entry in json_data: + URL = entry.get('url', '') + encoding = entry.get('encoding', '') + annotationKey = entry.get('annotation_key', '') + annotationValue = entry.get('annotation_value', '') + if URL == '' or encoding == '': + QMessageBox.warning( + None, + 'Textable', + "Selected JSON file doesn't have the right keys " + "and/or values.", + QMessageBox.Ok + ) + return + temp_URLs.append(( + URL, + encoding, + annotationKey, + annotationValue, + )) + self.URLs.extend(temp_URLs) + if temp_URLs: + self.sendButton.settingsChanged() + except ValueError: + QMessageBox.warning( + None, + 'Textable', + "Selected file is not in JSON format.", + QMessageBox.Ok + ) + return + + def exportList(self): + """Display a FileDialog and export URL list""" + toDump = list() + for URL in self.URLs: + toDump.append({ + 'url': URL[0], + 'encoding': URL[1], + }) + if URL[2] and URL[3]: + toDump[-1]['annotation_key'] = URL[2] + toDump[-1]['annotation_value'] = URL[3] + filePath, _ = QFileDialog.getSaveFileName( + self, + u'Export URL List', + self.lastLocation, + ) + + if filePath: + self.lastLocation = os.path.dirname(filePath) + outputFile = codecs.open( + filePath, + encoding='utf8', + mode='w', + errors='xmlcharrefreplace', + ) + outputFile.write( + normalizeCarriageReturns( + json.dumps(toDump, sort_keys=True, indent=4) + ) + ) + outputFile.close() + QMessageBox.information( + None, + 'Textable', + 'URL list correctly exported', + QMessageBox.Ok + ) + def moveUp(self): + """Move URL upward in URLs listbox""" + if self.selectedURLLabel: + index = self.selectedURLLabel[0] + if index > 0: + temp = self.URLs[index-1] + self.URLs[index-1] = self.URLs[index] + self.URLs[index] = temp + self.selectedURLLabel = [index-1] + self.sendButton.settingsChanged() + + def moveDown(self): + """Move URL downward in URLs listbox""" + if self.selectedURLLabel: + index = self.selectedURLLabel[0] + if index < len(self.URLs) - 1: + temp = self.URLs[index+1] + self.URLs[index+1] = self.URLs[index] + self.URLs[index] = temp + self.selectedURLLabel = [index+1] + self.sendButton.settingsChanged() + + def clearAll(self): + """Remove all URLs from URLs attr""" + del self.URLs[:] + del self.selectedURLLabel[:] + self.sendButton.settingsChanged() + + def remove(self): + """Remove URL from URLs attr""" + if self.selectedURLLabel: + index = self.selectedURLLabel[0] + self.URLs.pop(index) + del self.selectedURLLabel[:] + self.sendButton.settingsChanged() + + def add(self): + """Add URLs to URLs attr""" + URLList = re.split(r' +/ +', self.newURL) + for URL in URLList: + encoding = re.sub(r"[ ]\(.+", "", self.encoding) + self.URLs.append(( + URL, + encoding, + self.newAnnotationKey, + self.newAnnotationValue, + )) + self.sendButton.settingsChanged() + def updateGUI(self): + """Update GUI state""" + if self.displayAdvancedSettings: + if self.selectedURLLabel: + cachedLabel = self.selectedURLLabel[0] + else: + cachedLabel = None + del self.URLLabel[:] + if self.URLs: + URLs = [f[0] for f in self.URLs] + encodings = [f[1] for f in self.URLs] + annotations = ['{%s: %s}' % (f[2], f[3]) for f in self.URLs] + maxURLLen = max([len(n) for n in URLs]) + maxAnnoLen = max([len(a) for a in annotations]) + for index in range(len(self.URLs)): + format = u'%-' + str(maxURLLen + 2) + u's' + URLLabel = format % URLs[index] + if maxAnnoLen > 4: + if len(annotations[index]) > 4: + format = u'%-' + str(maxAnnoLen + 2) + u's' + URLLabel += format % annotations[index] + else: + URLLabel += u' ' * (maxAnnoLen + 2) + URLLabel += encodings[index] + self.URLLabel.append(URLLabel) + self.URLLabel = self.URLLabel + if cachedLabel is not None: + self.sendButton.sendIfPreCallback = None + self.selectedURLLabel = [cachedLabel] + self.sendButton.sendIfPreCallback = self.updateGUI + if self.newURL: + if ( + (self.newAnnotationKey and self.newAnnotationValue) or + (not self.newAnnotationKey and not self.newAnnotationValue) + ): + self.addButton.setDisabled(False) + else: + self.addButton.setDisabled(True) + else: + self.addButton.setDisabled(True) + if self.autoNumber: + self.autoNumberKeyLineEdit.setDisabled(False) + else: + self.autoNumberKeyLineEdit.setDisabled(True) + if self.importURLs: + self.importURLsKeyLineEdit.setDisabled(False) + else: + self.importURLsKeyLineEdit.setDisabled(True) + self.updateURLBoxButtons() + self.advancedSettings.setVisible(True) + else: + self.advancedSettings.setVisible(False) + + def updateURLBoxButtons(self): + """Update state of File box buttons""" + if self.selectedURLLabel: + self.removeButton.setDisabled(False) + if self.selectedURLLabel[0] > 0: + self.moveUpButton.setDisabled(False) + else: + self.moveUpButton.setDisabled(True) + if self.selectedURLLabel[0] < len(self.URLs) - 1: + self.moveDownButton.setDisabled(False) + else: + self.moveDownButton.setDisabled(True) + else: + self.moveUpButton.setDisabled(True) + self.moveDownButton.setDisabled(True) + self.removeButton.setDisabled(True) + if len(self.URLs): + self.clearAllButton.setDisabled(False) + self.exportButton.setDisabled(False) + else: + self.clearAllButton.setDisabled(True) + self.exportButton.setDisabled(True) + From b4c6f67d586afdef767188ed339ff72569ca9074 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Tue, 11 Mar 2025 08:26:05 +0100 Subject: [PATCH 03/86] cahier de specification V1 scihubator avec images min et principal --- specs/SCi-Hubator.rst | 106 ++++++++++++++++++++++++++ specs/images/scihubator_minimal.png | Bin 0 -> 23817 bytes specs/images/scihubator_principal.png | Bin 0 -> 34921 bytes 3 files changed, 106 insertions(+) create mode 100644 specs/SCi-Hubator.rst create mode 100644 specs/images/scihubator_minimal.png create mode 100644 specs/images/scihubator_principal.png diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst new file mode 100644 index 00000000..32564e75 --- /dev/null +++ b/specs/SCi-Hubator.rst @@ -0,0 +1,106 @@ +############################ +Specification widget SCI-HUbator +############################ + +1 Introduction +************** + +1.1 But du projet +================= +Créer un widget pour Orange Textable (v3.1.0) permettant l'importation et l'extraction de corpus tirés de `Sci-HUB `_ + +1.2 Aperçu des étapes +===================== +* Première version des spécifications: 13.03.2025 +* Remise des spécifications: 20.03.2025 +* Version alpha du projet: 17.04.2025 +* Version finale du projet: 22.05.2025 + +1.3 Equipe et résponsabilités +============================== + +* Luginbühl Colin (`colin.luginbuhl@unil.ch`_): + +.. _colin.luginbuhl@unil.ch: mailto:colin.luginbuhl@unil.ch + + - Specification + - extraction des données + - Code + - Documentation + +* Borgeaud Matthias (`matthias.borgeaud@unil.ch`_): + +.. _matthias.borgeaud@unil.ch: mailto:matthias.borgeaud@unil.ch + + - Spécification + - Code + - Documentation + - Vérification orthographe + +* Peretti-Poix Sarah (`sarah.peretti-poix@unil.ch`_): + +.. _sarah.peretti-poix@unil.ch: mailto:sarah.peretti-poix@unil.ch + + - Spécification + - GitHub + - Code + - Débuggage + +2. Technique +************ + +2.1 Dépendances +=============== +* Orange 3.18 +* Orange Textable 3.1.0 + + +2.2 Fonctionnalités minimales +============================= + +.. image:: images/scihubator_minimal.png + +* permettre l'importation de pdf tirés de SCI-HUB à l'aide d'un DOI et l'extraction du corpus textuel. +* créer et émettre une segmentation avec un segment (=Input) pour chaque partie du corpus importé (résumé/abstract, bibliographie...). +* traitement correct des références + +2.3 Fonctionnalités principales +=============================== + +.. image:: images/scihubator_principal.png + +* permettre l'importation de pdf tirés de SCI-HUB (à partir d'un DOI). +* permettre d'en tirer le texte. +* permettre la constitution d'une sélection de corpus multiples (add/remove/clear). +* créer et émettre une segmentation avec un segment (=Input) pour chaque partie du corpus importé (résumé/abstract, bibliographie...). +* traitement correct des références + +2.4 Fonctionnalités optionnelles +================================ +* créer et émettre une segmentation par thème. +* créer et émettre un résumé/abstract. +* créer et émettre un tableau de cross-reference. + +2.5 Tests +========= + +TODO + +3. Etapes +********* + +3.1 Version alpha +================= +* L'interface graphique est complètement construite. +* Les fonctionnalités minimales sont prises en charge par le logiciel. + +3.2 Remise et présentation +========================== +* Les fonctionnalités principales sont complétement prises en charge par le logiciel. +* La documentation du logiciel est complète. + + +4. Infrastructure +================= +Le projet est disponible sur GitHub à l'adresse `https://github.com/Olipper/orange3-textable-prototypes-' +`_ \ No newline at end of file diff --git a/specs/images/scihubator_minimal.png b/specs/images/scihubator_minimal.png new file mode 100644 index 0000000000000000000000000000000000000000..c98ed36d0aa3ddd413c673b1241115b31aac0407 GIT binary patch literal 23817 zcmbrm1yEgGmn{lOfZzlOt|7R)OVHr%?(XjH?(P=c-GaNj!@=F%?*6)8|F`<}>w10b zQg!MaiY@D`HRqUfjWIT%GEyS&Fjz2PU|{f~zXj!h_bV_k@TISiz^4p+1Oedfi#@-n z!dKwO(vK z?&pE0H}G@iYV=@o{)%W#v+Z68^K526D|-CXP&+o7{P` zX|o0sCM+gXQ`3>RZe|R)40ijV7W)Ic`%~4pxVVt;@LmIk+-Z}ndv{b&OAZ-~S_PVj zh{);bDKLFG&KDbBzI@R!GP>u>VICeH4(rzWt3wwP7uPe%`!UvNx!UY_g67uoZrX)T z_$6od=<@P1$8@%+{q25LMO|Ir$S5c^6*KMe(M70g5d|B2Gyocf&GVV5$!a~Wq7rEm zLrC_YGd!NIBe0lZjE#-Q#>c0R@7&_z<1u-?xPlS!Nw~N)K2h~C{?4C9`u43mS0Ffr zPWKZqlEXW<`lF+x*V|d?3?9$4=H}*N&0?e<=(e`D861vb%XP-_Sy@r{b0zW?o1K}! zU5Yi+k$yz?^!6^dI#L=>Wc(_gH{<2?e6Gh~LFN}?!h#28Xsy!|yUzY#LYEFB%Sn=- z3k{eISXfvpYHDB>4;?ss#so@%n-&xo>ocS(D2uqcaU4u!_EIr3-`UPn_sQo2OVQXk zFfc$e8nqJ9%b1juL>9&`Cx={8QWCiF!*k8?CoysE)zww3Q$3kny&5$F0zyi9`hhu5 zht^~!r!%n9r6mIS(>aNry0Qtt4Kp$_u5od|?CtGwaB&&aTh0Fbvs%=@eWm?^gQ4*7 z@TA+|a(`e&Lb|)Zh`{7Z758pzyvI%?y39D5;2(tIHa0fG;c=xTQYzbBZvASs-khNA zdi^Ir>@%&$)0oTE8eq)LPjHGgYYm`DrLziDYV;7fv`gfOrLwq&Z;xhgG%kEULoGGi z>Sq;ChBY)W-{0SxG(=xKT&+8A?)~-sytKS*$b*i7F?70IhyO_R>GS7QUT+@S_RAjq zvOQHjOH0ih>P_#|^mKhg!@@8QCam$DRpb)~jv~qQft+9dHja*aQ@H{^fBuxIGm;z| z8?(z`WoAySuBPkh>G>@#?yf=1gQo5EMC|@>UTCpg8*TXH>+AbZcmYEX>+2Kb;^M*p zA|)J++U;;qwrpOmMo(zN^I?5ZZnRFYY+g@aU*2T2uAzZ?3ei@|akswxRBKcmm%aGt zTLPtWRI-*^s6Q0q^#HcD!F}WM(o&3ibn~=HfqIiwbQzQ4$$S|)R%8$aEE?G5b};@- zxhf+94jW%6GBKHAsltAJu~a7L@oI<3as}1d**PySFH31TIx{d(C^w6y90-N#>Y=-~ zv_%eJq2oy;^+uDZ%T??4eHT~iO$BxaA~D(Rc7b@lmK)SxMMkI9!f9Tu|K}VJ9(H#2 zI+;ueVmxqf3Am0kC)?5Fs7oAmVw!u{30ZIDLB58ZSB|fbM<9iJa$CH|_ zHQVmn1B>qQa@KUZ-j>X4zA#lNo;K7_vup2n5!cP?%T_Q@!m)x4x5b+@ZG0?b%HYEve^Oy#;iXSLuj$yn#lY9 zxRd)JTcyQqwb?liWE*%2k0%GW`+Wfb8G^#XJWOvrfw0p@4)wsQ5#Xnr8N9;7%)V`| zic|m*T;qCUBpiY9D;NQnA=`Srm6=F5Lg(fFY#EPeq9SUrk(kHpl?}+5_D4{7xn^6E z+~{JX;|mnj&C@|P3NG&WLWR1hxOl#3JV^$xcUHbgv|O1IwcEqFq?#JmY>}jX zZxHd=PS*!C!6cDtYFZU7nyjkb#ZFP<(N&tjHBOpv< z+y|m-=>Q2oSEZc|AajlBEQwmZiEmdIFDyFE?pP}0-}S6}Afk}b(1aH&HR&co4~GI%%YC`l?t0Vg`Qo(y;qUK{zjO`cS!mbCJLe{IadELRp223d?q?tj zdj|(eZ|*1*OD~^Ks^o#3*U-?IGGSul;Mi{-t2G?Wn>Sl-Fjw9uuLSC*ArRNVs&dm= z%E`$kfd_e~D?UASi;Ic<;Nig|B`xNfB%0f+3Bown8fv#cka9X-8=ff?Ph~VlU^bi6 z0kRg%^*F-D$*IWu;~kN!$?0qbia$g7>B({YaAUH$S2UHuFaw|=XB8 zvwglb#bULR0BU-j(fG)XJFsT^Yc2K()aqzJbseL&ml8{&g630EQAw)ue%uabGM)Ki zZEfB8d`t<}`3Qpb^YgQ@x7P>O5X|Fdob{i+NmsWUxWbLbO?(_MZqxL4d!U#z*{9O5>KYN8pQWTLPr+?K#mM(u{ilUuHb)cAkCn>gumuXj*t#E__s1J65FrJEp~wKdklTB^ z{c}5wW+ZiWbu1>6ztj05N5IP{{AU#q6~R))`9PQCn$~GHUz*xrYzTm?pojR8a80~&eo?o4|KK|>~;o8nJVTB z<-^w)wpu4KWhn{+%gd<%%*4gS@ZIc>+gq5KHmCvj6afl=$=n}VquJ&^wT+ElTMBa` zu_-CP#l*rWj$MpseUMbcBO?ug(h9VH6pOQP0Dh1wmZFL$QITJR2erN71=^+?c4%c^ zFg9cv;not<^Z+dtCY=r#qtV#V?7O`z(7xgw+41L3r?9K|sU624h5tBkZ6yce^4;m< z=Q1UU4+Z+z^78WPhKBJwjW6-Tf_8Rxxtm!BqVt4=XhLy$WCaBUF-b{5092!)p{44h zcgMHMZp8l)NSo#VlW{8rn`?)xN2nmhPZcmC8WJeO4qbypK}v|mzsKZ*qle7jKL)fb z*-r5MAtD6hrvIM@{_F#;6rl1oF&^o^zuJF3XgLbZ7U=bnQBZCg=r}n!KYjXy*Fr`p zxM7G50vaeFYOforU!Y3S__;9IS&DISac}O(sDg;J<(d|Z19+a1s-i`n(Ke_z{f^LK zjc?m=$YZHI@*zEw`$xv71e3B(d1|hh;;~$0jMwPlq#gPv>4>wY_R?G8p4@eQcnsP( z32k7ji0|;PgJ;h+HGXD~E+NfQmS*aE&WBa)4o|64>&v~xAsI9LI+Q0E3cKySv-pOs zHw&*Mkvb3+fut`yykhz1NVdAWRA~C)i$KPJuaLQorz00PH*2+x^sy&xV9jF(n!@FM zPnDUua78p9ln&RRv*aht>ibOumfo7G67?hQ#v&{>PHQ?#?NYvF2E(s^9?}QYup%2aPy3N)vp~l_=+6 zq*VG4Ljg_u1BS`%g%n|3mcW&Dr_HnPIUM#7TOst=`t>h=!%IJrJ{>CE`|+vt+KNm*$M9?S-4 z2N5~EOo8B=g0q%KqBL0u+bDyc7M*uCU%PT#psq@W&iTj_z~Q7zY;^k2 z4EN3Vrs{W_gZox*F8=jB0?sbJru3TB?mX z^UXAs*9dkmn^0J3h>^5~A)~iIWEZ;Q`CPJHE~I}Zvba%UGym!E(sa?6VO6=7`x{+` z-h8WqTBimIB~!B^bdeFcc|8^s1#5Yfr2$(FW?Nh(wQHS-ss%Hag|@}7{5aMYx7n{H zZK^dbU${5DA-vt~%hx=voLB|C4cN(9*3Y&wx_ca6THGKMheqdt?&uPdpV!XvCB4CTVpMo*!`){IYFOH zB1O^LW5GtZ*m_Qqox8s2r#<9m*;wlHbDSnCV$(yhAluf>UbfA*x9`2%@UGW7J3MUj zPh3Tr&Q|MhyF@P>2bDG4FYC?-NU8~2e5UJR16dgY8o^Ng5Nvg@6KAbv|NRh}{ z3*C2eqvs0eZT`+66o_JLNmHfxm4JZ2$A_YK*+Pt%zWcX^#3vfOe!9t&r4e}NHmbDQ z#z@R2I~dx`Y>B~~m39^{l*K!eJfgf1b?yWTaOY&r+y{P;T>Nh;8Rt4kcW32thRrlg zj(BJk61_Z-%@x`Gg{=TA>lzLd`C`x-$-!FR`iwf#tjks^Aoo?8{V%B|g`<$g|0-!Yd+o$oU zkBT+EI?#TBHJzIbh^X3=C-6l(X*&|=+{vlIz zC{X2q&ejH$(Qg7C;*&3G9a90$UM4+0*y&H8JMf6><$hADO4JjU#3^fR-KXp$#?~r^ zHdUq6=hD}l9Q>^9W7UwS_j%o%$ws%b;LS{pD3YI6wd@XcYYL&af-Ho zn;NveT5`3b~Lwm z8XK2h#9;4@>h?FqC6dVa2R%3zlrhdl#?GxIHyKRWz&GRIuM-)ak_Jl_*gCni7qE1<;?8bk+`WG^2DEZT==`jfwUwGblSPA@U%*~gbrsoH^Od(A%8 zoqeXFyYxM(gai zHNLLUAZ7m@@IYP;Q!X>8shy)kgM%lTT8;JzvrIkV3X|3*4^sWhXC#fF_u&qINvnyq ziN&4LO#NyVqNz?_&HB1T6=RoaYzwa43TN6IS>t$Fb;%N*e}kugQ+h$KA3)vJNFA*G zB<$fr@59mGz`j7Du6sAzH!xuIM9uDUNg$cVG`!fuV!a`8cRUYUNGJPMZjmwPTEef9 zX2(*xWufrTh*S1bcen3&I_rVCF0e(8)`)TWGOUZkW+;iv$q?vreC;5jw-cC+`RYaH z==~Pl!hH6--76^midKhG-{`fjX|*B6VnH0})7u?cCf~m1|iS(TCvN%1WO6gE_U2&&oN|tGu?q)4=(`T;Xb53m2G_ z(JqIV3Ns=)ybUZ+7C&%$awH8?n|E-MCj#gOEWxd#HKY`@7>rs+vbCuT`wr6C-CsG= zDB7M{A6%>)9~1qPX>DEh9vl#v23@?+J`3X#Jtq5S@OGreD%D}o9f6rbxKHww zHk$ucF7qm~Je|D#Bb(_&Nr2oa?kDc978XN7_O9%NEle6I2c4UM{t@Vl4Us#OJS=iVIB;$!K zxm0D|qtQGyb@sS-m~$HPQ+R2i+9q}q_F>? z{`F3Lb!*;tx$f(6H)=zXW=cMN=k8_Zok$<~=@Q}Ves~DYSk@f0GyLJmJ!m$|`LSqO zoXKiF*7+eJ-%;r1RM}wFXL28I&`V31BH_BgVkfq|!%z^NE@nC2f9XT(^Q(CBK$9>c zi4|-z609$rB}KsTuxavto1iT?lS^V!QY0K4Sea75&TiCHj<8Q(hY5=wE3&zzMOR-x zevgSgh>d~*#@*e$yrN>-gvo@-4!j0QIxLS2ptsG;C}d@2U0hua*)^jGSr{362L>SR zZ*V4Rk@>ll0RD7$ch^FD(l%QqZHk`@+ipa!5?6gD01b3BLhV1pNgXh<_u{6P%cHBS z3v8By|BcBH8}bAAyQrwB$Hzxh6EA4nZ|G=fK`kxp^QDUJD}^CA8m$hY0D-l2a*}@G zO57*32C(NQEA>aSGy=Ol{r!P4F)^RUDPQ`8GMIAb^K-l@|Fzfp7s61gghUpn%>DUt z-XAXC?qbW;K{->s3iawnu;0xoLz1a`Rm^RoGL0>bDD6?!P_Wsg-kb|XXKOi)bPVMJ z+E$NOHqIol=Y#6C9bmN>dfajQanR{EnLaAo;ob5q!&9XhToVlElckBTRMeb~ZFSy% zd0WZnf1X_nlH&jqd$evpT~9Y$&UT{+DE;msUT#}_;AbuNLQ`u>{)z? zJMXk=?e_asb-5f$5uw!_eUm&#^x^eU35>YSV{q;LJ43Yd zQ8cxFq^decd&(k_4#y{93qmf6j8UlMORr(-_J{7xwFLK-ume6qrs4*b=4TWx8_2pB zvnR`IWUJJ_HmAx(XC(v1bv!wSEqY68tMYkrqyrN;K{tNZsu`9&Gwk&qxQ%C=$T1fu zwDl^@U#3dMi889Rc7y0&$P-s7F;yB!@XvlvUWf&_6rqB6Y9M^6)8#;iR#AtNf&qA2 z!h8EnPVSexmS?ctO!piUSpv%urYTN7h9{awQya;C8UlvD*(Q&l)amBR1(tDGcCjd> zDHbXPTJ&b93FazfCYNS7TDKCs!ulKn10KKBOVO~sK74|!V5EtH1ntDh*tnTsmbfP& zgO;-jwbTfz9vWEftjxrY|lYAD7>U8++ahTbux=BKQG5TG{fy7 zSZYY$sSDzzTHlr)Tp&LGUerC&4{;NcF1XeOo9PsuUK7>a^4jD9OL6BOoz_M|e-mJ>SM%$AhNPXbT1`ikvhFPCzYscUBUpJ92+f;$HK8u~BjO(s;W zXk4>->h7y;Rml`Nn0xO!ld1<=h2nmFFis@aLmc>ox{RN3&=dKW*at zs;iTKax(8(_XO2D!cnNl#Svfdj5uVDj_;b|tTaZVe6zz5`=cI}|05_kc<1yqA~jW` z=8qB}H!eFHrb*UIp}HV)$sg z4%Amy@(*;_emgik9P0Lm%67v1fez4;0MCqOqQ&l{(D(HCXtUh|!OzdXTjV-P)^brl zr1}#*NlhMTYS$WD|A$bHBgi0W`#}jvl^6z}Z zdi`YE=z^=dbxY`(gGdxt0W_Oqi4o!S<)u^hr*v5EzxDY-L}CZO9Im#^iY8bXy<~j!x!n(0WN)Z~FdwWBkzy zzvdnE=^0Wn?-{$xp4*W7^Xux>O=O$89q~OFZJ^hw`9ZY|4V-2a zbZ=UVeT9pKU@RJr>g%GLzfmghC_VI^G?c&B`@_bw+Ii|Bh^c=a$i;WRX@eeT?ljt( zMlJsyijiD(@6+&WXD=OXaC+m;*x5VG@h@=~ZY*r5xa|TVG^BnRm zgXm+M_C8OV`KdD>oCwC=q$q@88SRc1s?0iDTQlW&>WZ1UbN6oU{<&Yr;E!Ways*7AL);nrQ zf7S=6#Mk;@7~FJuhCvuf!3>VRL_s1G+{?o`lIC@X{W(J3RDJ`yD>=xfdcwiz{%WF-4~3qSbh0&h3C{d=N1= z$Q7Iinoyzi^1P<7kFLs`ndOeHcP+UB)-aYoWNr9J?msX>eE}xdu9g^}ssDwNqqbB< zySoN?`T2mt%YYV-B>ihZMZ(I;YH4Z7fL$_*Fe)spXJZ2oP>nFZ%Z89r=_~Zj%_#s1 z`Q`QXh+Qj=fCXR;0d$J}eLI*0BxyiNB?L6@)kXU?(j=04q{*O++7$D_B&OUzmsY#c zod1S9Pu{TwodyI30y;p-OTa@-T^*nXR}qw<@bBjE5lTr&{3IhI)4mA^3PLkbxX z%*{ueZFdf5ixIOu?=j)An6?0?M+64_j|+9(J(hGdtKETx$Tb4KpwxIU4M=bH=jDuXl*gz!2A=@t@mzOqx zxq+V1-DdG=D3%CN<$h{YuC%){0@5+LN+LhkAl$#I{gaz7MuS zflGsf#nmTB{HQS+(*H%6`B%jMkMtJz0_?r-XqY*YA%5;8{8XRop=E6*1w(vAFdV3P zBLXDN1rEycmw8(V(WG@E`MIowoU@zhpiJaJ(3&-=lz|?LJUe@m_V5;|DsOX@vHY*D}h2j%B?rq{_%qF_T}h{ zdzY!`-EnusdWCmSb}Si1R;nk6Karkqb%a2T<8j&z2v97hK{POwrbgVnrCP}hs;a#; zTI;Kktr7)jOv&XK>nD&L=K?-^6si;F}LQr@Ry~uUQa$fIlYBC zrdXjDk;%Ou^FB-e)s5YRvAGuw5+se=Nrqzy4?@h)lV-T#xU#tdG>B`vSgm}jd zNBXqpp7P){2PC$3q~24E8}KYeM-rYNcH}|P*9U#psa+qCM{2kwtW`RPr9MY2vNcLB zs7=XRVS{-?mZA3eIg*6*Btc^x1_E%hwg}B^rr?ZWUAJf`$>;h95i2+^CT#XJ=?uLO zI#3Cal13DFr|GX~@kHu3y`@MjRw})7m4#E_CYd(25`;e}=tmK#j^>b~OG5(LtUuQm zo@WeRke=(v#j(E};54>Epqy3+c)xuav?|o;fkW?taalf|KKagsAjP)EK6s?=CX+zr zXZ(X_A3^GU@2dWj{Ms)i>kd0-9P&ucNHxX%p;J?f=-*HRpOky7;=&+Bj5#Z_xdig^ za(<@?fq$<+IxzKNfjxe>7&)6vm)q$2LHltu_QKmPU}#ULsXaJoS+=Fk5(6XIMOgEo z;`Vej)m(4z7yDBF=33$K83i4mW6nU--xq(Y>6{vi*;Fdsw~TzYm1hCWgnZVWW0RGm zR|Niz{0O(toEMK+l)iZ6M4-gUhU}N`FOTZI+#MbMT~S|11xgDBzI3EzcdE~&-&y{1 z<_ei-tArfH{7?Gi|E8I4F$T#AV#@pn9F+b$9Bhli{~-~amao4Lg%^1&je-K|=7%e4 z@k&a^u6s_xt$ewL{r)tR0SbtoLXD86tVe{?3JDKyA~NzqZlaC1tTGq{&ny13c6-8| zKM`eZf2{OEpM(bJb(LOni{0vI{7z*yv9{8%l$*Jpgg=#GSEB4!D zALB7QH2vYHXGU{9Bq(8)AJr0=Bb~P#@$aDoPgBkjYM4XC*(`(oW8sUP$KosXh)*|R z-$tLU8SDGRT9v6p>Z}n&FX~-LhJDQVxpoZrm~BqjG$q zda~JSx7v84b#`s-IOgb+iN+*-fdejKqLE@-TJ3Cj#9ZWi>Z!t2UL)7AreGV3C~M=o&3>uiT1Lz2v|vzIs6a*@!~? zNcsKnoQ+ZnHN#5RJiti>m&$iwrj>B?PC7kcUXC>z7&Je!eSq>;oV!!sy8ROdboxS2 z68=XYdZu<>Mit_oKNQ`8%1qaV6uQt*F>cAX!*FRG&y5VnfS=9-VU7M@=omv$H>IdbL@M zc=?LqobY(1Z(52}-wR?GH%jMTPi(_wxnrV`RKC*tO^cjd&HCPCEMHOYHNAG<*S{D= zYmNqF-@&OkWyE(mc1s@kY2WC+K2JhVWUGlz?qW))IQX}HKV)wt3((USV8e8Z2-M7b zG@5e8=}Z>tO@+syW=-{$3byr-73nFC&^HahOyqFxv)z$%+I$-)wEUo8QEe)epMOO- zreC(Go(xg&-HPHi!xh{A3oKxDq-PD&A-gl9ozCdtxa@( zrgUVbWOct@nc7dN2g?+fguJWh4>de#F^bTAc_vagThGRtP-9|wcW^KJ-Va0{GeSKU zPgs!_!jhUQSYv{@3_iX)E*7OW*4+J160Wp}>~HCARWo(%xN4EOdoQ_HTvT*@@U&gg|&jCps*+~e`}(-t$2Lq~ZFCVI?JMdZ*hvEJ!r@>N7({fnS< zp`WZoADT*LE^N>f{Wi?@J^l27e-3xYs9VUd5S;Or%FWMD#AoZQuhk`@EXEPb_?Mb> z;pN+sK%3c6fqjQ2at!b3coP+?|MU&ObrvqtkS*I}Y&T(8EY(LFLAZxow3&87im{0F z&lpkfH8F22hR{@3m*}dY8$%c2v~i^=A-u1!Hwel(qMpg8h{UQ3+ldR)ugsp@i?iJr z?mnq?4|1IX_F~5xrc<{<{N5jd`Oc`nyC$Ap&0F3ttp~YDK>FufyV`itlyv>L26qdT zYrL+<6Ru<2UQqFILs!eZbrml9SndaSza!0ITfg9Ld&f7*<$1ba(}l~FN#6yVpa3oOt&`yT9DzVz0;Li|-XE;k<{tS^#&zdfsu_qS(H`4g5y>~v zzQRSW@BixNNx^$dXE`HlhZs5s1Xjh!u$u zDZIA6UY98hJbgmR*}?xO<-g$){>_K?pDQkVmQ!j*hJ=Fy@Fz4g+}cO=xs!qTz_qUch%>Q85Hj zBO*rqFzm<4-+sTdAEgw1U@&&H7P7ZoBeFT40@jm^ygfcEU;Yfhaw#Jt)42}~4^KT*ikFx2voG(fTL3Ehzi}%nmkm6hgkQ2GvTK6Dgo=0@-VTwMb2<1kVM}XSuq9l0WBw)% z?@?peH+Qm#3laHcimq{kk+$56`ie9kwG5r z0f-Wg2U3(ILU>P}DT{fI@z}4g?}98D;(uK}%*kI;m)vpaxs&a0drXts@wylNy?4vC ze$oG0;k921<1!O_r*yxBj&1w1(?(QPQQI z$O9whNXSC|!BVmpI|y}NpWYdC#XLz@V@Z7M@RTA{e6FK_I)gxK=;#Kt%y<2tV6_g{ z{L^%?mz_pKpdlj7#oe4~!JN(?gu zjLkZ_X!UjClq*&W8=ZCS73%6HDf-W4wza=kmtWrW+G=Z0$HYO~FGq)gcc(A1!hv#F ze4#`%+vkELLieFJ;x}J6P3M`5v+upavG9vl2bWr(=#qb&$7Ch_Egbhov760C?{G{} zJQ6hD;qT0L_H*g*i$fbN%s*(hY;Ouwe6Qm=e>Ydkg?2#0Zu0ar8OFUs4 zbM-HlitYq(u;&5~pggHf?~kXK$Q6opm$nyAC{r$T6rl*`AH^mS_0|sQ^zp)n+vDsp~;OK>D926?5)>fQUa zyKZ=8=-io4R&Vqhma@>9QlGlf-^w36>L!& zp=7ok=-3 z(f~67jtB)hKNp^G{x?9|YHM?EoZWTFQ2Baw8o%*>>6+H?<@a#vM?#qNj_>;e8>ktL z^dtKk7ewjqP5kz3bc#dGR%@`d^GEb+EaDT4t(zSexvn=zv57`;RpAHoJMv<5rHe)b zG~qRYHeqM&j=O{?E4ktXZe4xZmj;WmVC^eU_VW!bcp$vC^wEu`Hxp=r2Sb~{@dGx1iu z6C5{VHoM}-3(pZUZ?lzxT(dI^jDNduc{gP~4%1v=Y{&XLFo>LymkMyg7KY}_WPcW7 zP908cD~v^;f9hascQM&mFyZR&gY3ULf96~~|9C}4yH@)Pwov?iOA|E!S^DsLT*Gz6 z{Zq@FZhL*~Uhw&);Du3&Q`q;i$(T1ux$K!*FuHG@`s{5#=J7jw;);=iFP?Fvd7-E@ zDDs)h2YY4!YW`EJO+B=E$=Z(;Kr;;OaHEShckDa8WR1|oRD9H);M%}e|98_j_Z`xK zMsOC2cck$-3WDuOWj1EptwZjYD!OC{pCd@hA_@KA05pW_|sNuqEUea#gxXP61&JZ|t3*xAqFfgYlCK2>Z*?D+|e?=aUj(<2bMyS+aE! zDc!iK`VK>=|``PA#pzEmv37q{?>f(E1n&hUm)m&YAr!!bI`Z_ zO&XSN5-U>mpU40=w^sOeUD1tFe%NEDOi);baLsWmeL4rjg2C?frvD-537h)>Yra@w zkVmID;(zs}ah6TeWr|Y{T-uF;jkvtXH}uo(<4L!_=*LvYD0gTX>hkXg54FB~wZEGG zeBNO^d^+c^w0QJMODvt)enBZX#TTeh?gS-2sLRezhBJIuyW9ZL&45WHKjkVC2(T6# zzwU*+=QD0tSNtFkH#B^QmP7~s0%lDeJ^Jd)kntJ>NsFK-fJ}Ck`}*iaH1hKFO(vfx zyRswdSE$~4a237nq^Q@aT%;KDhOVPtk~aR|p{EP=8H-!0fliHh9|o;2ET@CCBJs5u z9D8HhaMrSzyqmQOraT!>2j_2Rl8Y)&)0A^nI6h6u_{?pdqZ=*|bl+MWxz^2+dnX5j zYZcS!?G)KaYD>7=7+`-*^fn*PhHx^4&hR8*)DUy)ahBLlRVMa~o)K~*+z!XM*>i4y zOJT@c**yK#ZmCk7)}P(d=c%X-mG0ym5|EVzsc^O;b}e^I2FWM0b)C4Eo?;CA-K4qN zx~PhUtqW#2R`J}&Y3+MjpZ#NJhhogwWX7RE>99ZB55;DGgmIG=cs0M<@N?<^WkuIY zm@#5J`+NfIz6Oj>OYez-duZ&=x8ypHw7$7VhF%8tVzv|dh_+4GdQCPxR$+}5W1o*( zw)bp$3tbKL2xv4{2UoQ(+#DgkOdG2Xb~Pj)UGa9B9f(y-r?c7Z;`3CM?L21-VAPjT zp*Uyk%%ma>G*fS##g2wPOGm*Qd*y5flbYV%fYWGkP1JUlNSrYy;i`HEGo~uy44qEj z)tIxyz6~POf!1MCz@Ia3mNoSu-6ynnr%v5)aG4{tX?E8lhOJb=Oh%_l%w3&m;J42+ zC*dIhcFfbR%=nLakAltoguu~yMMXj?PvkN3M#f9~%R+>K)} zFdWu@{x1NWQ=#khB4(srdJHiq`Jy|WqlTkNrrAt>CgmzC9_ajjIKzzlS*|LDJtaBE z^@gHPtK_+1bbF;;w!7k zlNfY9G^#*ucE`I_^PDyy8^&>`Po8t@PI> zNYNbG5*TgeA8WMdD@`D5U9!Y7tc1UEo<9d6gi?NZ}$USwD~LMEobK=G?mg2$QY8G9~jjFR7*%-U>ANm^;d?9Qi;;l z6o-%~A&X1!>qYQFL}K|bxhpe;VYJ;Aimi8S;!}O~QXu{o_rf#Dlfd~fmg;^m#?JVV zg{!GbbLVKFu|glu;=ib*)>1!=geLWp>UGlu>Z$=3s#7H-3f0&9aXqncxqlyn1I=EBp&-Vv6r1f~RD z6k5}ek`jcYFeZgbGcv+*v+-Dr2P2!{K#Mo(EMKeb*ZX?b(UoI@0^*nyugDG_sd7bD zg;b*Mao)N#|DZ42E!~Xp%#w7olLW*Sw~5Nc1K&P$cze}f^RmLohZR+KGH3|qy80f( zy9iFlh^`A5YVp?#b*jOTQ6S4VLKjL4$8O#~aY!2tgNEzTDQ4c5JAIMp*UgU4#O>q7uG9+GOMJ~Qo#3m4zz$8T~9X& z?!lyYc(G*kxcR$8&zG#l{PO(%!GfR^3?q9A8eDMwpFR{%&{ux+Mb~oZkot@Qa#jQJ z(a$85C@vW?`11OeF=DZK{E9zShWK-b6c^L;}Xnt`6;A9wbRz-J_!~Da^Sg3 zGztY2GjpF6h&7e+q#p=1A6?$?q6TmYCXLz8R|rgX0(3t+?+cyjwfEb1>vi{r87A=) zFw%!w@WB$$Mh%7qv0)}8kux)N_tAum2k+06CJ61?n{AjRk+zHUWf7_zq1x#FGA2PU z(VoQXV#mHp#~Y1W7QnnIAwo}9%z4=qY-u=TxhD`G4NAw9Y;jsmgFQH7dke-LbXvA0 z8;kN+KVz#Mk3s=3nOko#(cI}ZRZr5d56gcbN^$Xjm2%c!QN-^aM^R!y5SE6erMp4t zZlt?Gx@$>6kw!p5I;2~=L6%s$L0|#t5|&yzzU#gB-1`UIIcLty4>M;z^TRyPocHs7 zza%PNeoMR9y_}xQVm;7a0+Ie^Or+8~+P2_eBK%-bzfRA7AE0s2rVzV7+aJoCDb<=# zECp>H8D|fO(tC!n#iR)p@a$WZ0Rr$NqlMJU+i(=6g>OllTTX?jUJx!4CI@|qzCI*w zNh^C{FI{Q0WS%$7NM+S_b@it=V}x)1H`a*a@`KFZChOx2Q#QyNN#QXGgUmLsj@EBy=a5P za#*n(cUEgcJj&L9%kBd2L@}R;2WrEy%=w4$`cC)otstkz8-c~Jq-0>lqSw$%__&-x zp&Vc1>lXh@x%CU`L%_0+3A-tjSy@-{z#FG<@S%z=8VX_TX`FOC@UoPch;TBdMD_&0 zXJdR<(`}bx6#SsASDQEIasU=&7C46iwwYh>*D>4Ei#4;_IuDbLhSHv2hfQtVU8sRy?fwC6P#;64IzXE1HZV1!(42W#Ffptj{az zXLsh!NuSw_au~>F89W1A}0e zeI6~Cd|?05`}qmQR13jJRFKLu28#{?>xUzpMs?0ZgJM=&yNn71UX#2&7SJS}7DuH-oQG(H zBAmB7f{sorWslzl@||#P)9JnYa_$11<+6-Z%-wf}spDOZyw$k9=k?zSPpV z2zai!{RwUor~#|~$(%st0*~(x{T--ZA0e=P*=VB^D26!l=k@gD%0ZyK``(d9zPXAh z?Cjt!-Z^f7+bd3?N`WTaRaOZ4%uA~DV;@3AS0o{2jO-k$MG(d*CNB!o+Q3&oDvKmU zJJuc|MS*hD>w?G{pRs|E6U07FV?VrVtw}rf5;?;7`>o#>{kFcm=r*$NV@{0Vsr4fT zT2qFcW)~5|cqrRa9Y)2i0CvU(l^p=&!*65}{2T9_Zpk5nl3o1qPwVgjeCjvM|E;g_>s*qa~2H{!XzO z$|C?lND!Wf(7jrKm_5Y+9L`s=M83BJ+5vr?s9hmdOVCjSas>9xK0OAGhwST+s68p; zbrVQzr6hTJ@>X05TFK-EAzqPathPhh2PK}fjT{a?1ykv4Zk9(Xq%cJ?^a*}U(AV-0 zsSC$bH5<)^{rF8gDJydzG$*ie&wK6;@AzKvG9lzx ztIdyd*Q3?dmo*CWv=|XESgN|;$)DPrDYPgzM38ekivKS<*VU)s z-yP68OH4pP+Q#LYa|DKW!rqO+f?l-7T5K2Z zUwAb_rt5@F!h-+kP8kUk{?{U`A-=rhs}bG@$z}I5=kEOH=D%)w!Jl{-Ucgg%qlQsm zx7;0i`8PB{rl%9DwR$6&l?eP3DK>YZ;=H*&bY0t%8G@&^bv-$tQcI%C?dj$vKe2;=ll<<^h z@SIs7t)}ocx%(w1QJit_x8O{nkSk7(FA-dYU{X?62S9bmSj!@@o0)so?|=oN*CLdH zD<1}RnBNCpUjiC-oGgOTAEs*t4#7O0rmiYQJeBQN0~z9qaV=gO8ItMT8@)${U*!i*wwPfUI1F~zywFOn(>s;vQZKTi&`+> z!_S#S2_dO#RsnVUUf3ZfFo|U>s*1y)Ulf}>)y|JY69ztSKUNXD;89wuTE6t~9$n@N zyrJY6=<~Q#W{gLx*^!}4@J>)?aFPnxdFHa(+B@z}N+Dt>G<@Jq7OO5N^cEm*^|?Wz z_v(*r$qq;X!utX1?ra2HCi?BNES;ypY5 zp5B2lGzaArBG}IIDcmFIPjltL+SZdVb{T1vab_N-U2Dh4W$k;rCs$gKQ2_7)@qPnP z`c7R7^5x^tAiIKBnvkXohmw&WcZ#JfBf=c-eYx@JmV9fsrps8jnBn-|GN|2AD^L-S z?~LWf99bP<(j`88C<**O*7i*G2^K0KkO0L}2cALwr6@(L+f8$QT$8FLbvPcVzm6CD2rqYxDPN9O$T zy7Q7M%W76~c!E()jehR;s~MJ8{VYj9LXwQkloS)C;p**5?J~Qgg<1f-R*Bn*H);Fr z>ITGUoh^qiBh+3TC|sRHp;d-g+@H!USxh6XQN}VM%mE~w2Q3wF!}*%2_C1*zQ9aST z-q_Ef#nU&eUxI-mDqPaTbAW@YRtl@Kbi!2G_p0F@=U_MUH!%yxyS8Ldjn|nU)Xko0 zmoXQnb>wPVsl=R%@Y{#I;x&>FWe}$+|^O$qT$&yzClO6jsTWMZ>+f>v}Rp{j; zX7->9BJc$=Gf9^=?MmUO#jIB$ed@6N4+DG^!~Pk`XqS(HeBQ+IAuJH*zFANfFF>fKYd(WxWk0L++vExQR)LJW3s5|p9WM@Ai9s@(3>oR#$ubJ@PgkJ6drn^5 zJ%Zc(I9>w=f(?eLoDRWfrvvGH*J24os$^Dc-U8jC%pp~p^>f%=CVLWF*8=((Ml->I zB+bez0nUah28tSz7+QK}C4bFzsW%U+b3&^s z?Hu-1CP*z{r56=3v%-Uyci@>KQXCM2d-bN7_=&^>Hi4w#EfidJ><@f~g1e z-@XpYox|m_(fyM(`tZ91Sy2l6rM~F-V5+*^)e$n88xI?SPv8%3_#+*n`#Yi^WuvlB znEfNydNThsN^7tkg$328UI$kxKS{nhuP@@e1V!rn4T3%QH)ncAbN6ib2aY?xn(>e7 zu}I9KKQ6FKWHLq~*HwizkMMyol97pMQP(USc{c074L z%YPTy_5EMdEx`MK-*BT&_S2XnWR4{=a+c&tk**q3>a%o99CIlDf3ljT+4+1?L5a8da zYq6^%ZM|biI2;l!RHF&z<>f^p;U?$isyb?sv_GMpiQEY!kqA0EYJCiAB_JTE^*gmh z!zSrLdVs<3&MP+$kMj5fez|;Nj)!gmXCENwD5k#toONoSl;ybQy#MaNtGeD-Z#A05h zlUUO06OoaT<{3(z$PSLt~4dso~#4sh`*DU(4r9d`J4>4C8(up0tEXyEyJ zF%AM*mV4`L-#;SWzU8#mplfHjM_p(|K3rZt0vTX@G-*RgNKaR^wx(B8Q$r%FxC5`< zP;fvZeMlp^{Za!n5>XgZfwTR78Y?a9IXb%D47oC5s--3N<$5P3La^+BqhF_>ysqwR zM4fpAqv)MLND&qt;X%HCUp1$0zW(pD_~NJ8QO;aPaSn@^McnIFe!u;Ib9LigLqSGL zQGY&k918Qbt{@~f2<0PH@b$BQdC$s9q*$$2oBH zjg~gJua(t`FbRxJAep>P?ygS(ehnT)W>9{>FtZUEA?AB!64)xu5&Gh^GQ3)MFlS8hGSOE?QTGrv9f z>nGcbU9G-vb2Swar;ORaUl`rG`uCbyd?RUoWMNG6n`vt#{x#?siMbzsm4#s2gNJ@f zc{A2IaDKF1*{d~@k|Gf-dsHFmu#%+Tm&{KboWl}eMMEVz0S@%4MyIM4Qjhp*#@QKVFs?`xXQ+1205S%-d^(e3vU)yP z+k1&Z)iBLQ!x(x5SGA}?IH)-thD!Fj*xto4bZ6hT%)V~VnOS^SLN~_edXC6jWm_eJ zj=M_+^6p}A+@X8gdVXv>uJjld01HgBx}L3+bWhs-!gN7!QNxG4DWNKffPIQDTY)sdt0)2XNC%bI+^W`k1;Id{s z8z*dDU82w|A~Nd2Iz~H!%tOu(PY5x-VG+nKL>}L|Edpd!r3@|%6W8N?{A3pxA~JHR zYY2PtCVP-)@3}qs;FlU;Wv&0}AtQV+zIF+L@LSrhm@x z2<+}bK;>I>+%owMbtk*X3g^e7l<`SPhjK&%^xJ*dk;u>;B$E%BX4nYd?!=x5SpO={ zac{uK$#L81u&OT`YA)6N5>dyt1dRu+`ThBk}*&E->;~mMgs8~Ff%|e^7yJEF*YgkSWC6cZ7IU=Io zV|zHH@;E7ZJABRWhnxE$xSUroRe-d&*IsP+4{JpcKP&0)Dd+2NJIkQT9 zo+O2F{$H?*MXn-e+b>g@Q@nA;DqR}KIrdFHkjO|{WO|hw;Sd8U- zx_39{G<)Sza5+68FHe}l9#@zn8tf_HaotNA2T?`f<9yl+-pqB%qC z8qLp=9$}_!8J-96d5a<_;#F>4fSC0%>I85QR>jrODZ-ltB(mRBWVEc`D?q{U6Xk3Z z_a}Hz)f-wx&o2yWHNj%@l1TB-i7X8u@D2gBJ~Q+!xZy>Ak-t&bkHHLU^UItKl$Z!h zy&S**-(ZMjlT4n|kf%ieGmDd zo8_JFMqd^oYqvmFVR#5Gn-apBbS&_Bt#Dl`f_O$F5wc=Zas8$O_mR>t&skFI2g$fG z6UB*#RrC2_I<04#IkjsKWRKh$AoWvkOt>vYRgXslGu?QxHk4_m+N&{Dhqhwlk`M;4 zy1ektnn0srj^5T1vvAD#~`R@VS~(ebpL z^ART!zWxY#ED`esOSa{2ch04n`$-c=QH^w-+>2I*Q2U}VWY#FQf-!Ku`p_a z5E&U62VDH9!fUz|r5N!fB$bus?c2<(EQ+(UGh_%+qD;F$vwN9^tUeN2QM4D%T&5kZ z!XPazjmpl>?&al${IA`9LV>JdsXTNx1|wnQI5zrV8AiPe078j3CU7oIWwIeX`QC|HQ<=#0ng^m|3|P*n^hyF(Dv6L5K?r z{BTV@T6R%YGoo=_`mb?j*#SPMRxnK{X-yRICR zDb1N_va^`xvQ_zjX*c$!68 zNJ;63Qn!932A@m@->?qoxx3Bl@w>D%85x=X(UB!^0h}H&hDiJTe9}U##pd?5ND7

F|$|%!FnLE_a}1lfWZX%nE3dB;$q4W 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 DMG$)l literal 0 HcmV?d00001 From 82a241bb8f5730adb394b478dece6af2f6687611 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 13 Mar 2025 10:36:53 +0100 Subject: [PATCH 04/86] GUI des advanced settings, mais ne fonctionne pas ! Juste les graphismes. --- orangecontrib/textable_prototypes/widgets/SciHubatorTest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 396d7650..3b4258e4 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -146,7 +146,7 @@ def __init__(self): widget=iBox, master=self, value='importText', - label=u'Text', + label=u'Top Level', labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( @@ -329,7 +329,7 @@ def __init__(self): widget=adviBox, master=self, value='importText', - label=u'Text', + label=u'Top Level ...', labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( From 414908ff4890f2085040ed2387e41a950fd90735 Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:44:42 +0100 Subject: [PATCH 05/86] Update SCi-Hubator.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changements rapides donnés pas M. Xanthos --- specs/SCi-Hubator.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index 32564e75..fdbe11c8 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -7,7 +7,7 @@ Specification widget SCI-HUbator 1.1 But du projet ================= -Créer un widget pour Orange Textable (v3.1.0) permettant l'importation et l'extraction de corpus tirés de `Sci-HUB `_ +Créer un widget pour Orange Textable (v3.1.2) permettant l'importation et l'extraction de corpus tirés de `Sci-HUB `_ 1.2 Aperçu des étapes ===================== @@ -51,8 +51,9 @@ Créer un widget pour Orange Textable (v3.1.0) permettant l'importation et l'ext 2.1 Dépendances =============== -* Orange 3.18 -* Orange Textable 3.1.0 +* Orange 3.38 +* Orange Textable 3.1.2 +* sci-hub.py 2.2 Fonctionnalités minimales @@ -61,8 +62,7 @@ Créer un widget pour Orange Textable (v3.1.0) permettant l'importation et l'ext .. image:: images/scihubator_minimal.png * permettre l'importation de pdf tirés de SCI-HUB à l'aide d'un DOI et l'extraction du corpus textuel. -* créer et émettre une segmentation avec un segment (=Input) pour chaque partie du corpus importé (résumé/abstract, bibliographie...). -* traitement correct des références +* créer et émettre une segmentation avec un segment (=Input) comprenant l'entièreté du texte du PDF. 2.3 Fonctionnalités principales =============================== @@ -80,6 +80,7 @@ Créer un widget pour Orange Textable (v3.1.0) permettant l'importation et l'ext * créer et émettre une segmentation par thème. * créer et émettre un résumé/abstract. * créer et émettre un tableau de cross-reference. +* importer un JSON contenant des nombreux liens 2.5 Tests ========= @@ -102,5 +103,5 @@ TODO 4. Infrastructure ================= -Le projet est disponible sur GitHub à l'adresse `https://github.com/Olipper/orange3-textable-prototypes-' -`_ \ No newline at end of file +Le projet est disponible sur GitHub à l'adresse `https://github.com/sarahperettipoix/orange3-textable-prototypes' +`_ From 2026476acd0e95300979534913a25e140da281c4 Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:48:40 +0100 Subject: [PATCH 06/86] Update SCi-Hubator.rst enlever ' --- specs/SCi-Hubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index fdbe11c8..847def72 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -104,4 +104,4 @@ TODO 4. Infrastructure ================= Le projet est disponible sur GitHub à l'adresse `https://github.com/sarahperettipoix/orange3-textable-prototypes' -`_ +_ From a51961a59af3780b056f88172940c54d13e6ced4 Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:05:24 +0100 Subject: [PATCH 07/86] Update SCi-Hubator.rst Ajout de Orsowen --- specs/SCi-Hubator.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index 847def72..4b193397 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -46,6 +46,14 @@ Créer un widget pour Orange Textable (v3.1.2) permettant l'importation et l'ext - Code - Débuggage +* Chétioui Orsowen (`orsowen.chetioui@unil.ch`_): + +.. _orsowen.chetioui@unil.ch: mailto:orsowen.chetioui@unil.ch + + - Spécification + - Code + - Débuggage + 2. Technique ************ From 3796fe363619498d59f9acb819cd15f1c376db29 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 13 Mar 2025 12:05:34 +0100 Subject: [PATCH 08/86] =?UTF-8?q?Changement=20GUI=20comme=20demand=C3=A9?= =?UTF-8?q?=20par=20M.=20Xanthos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/SciHubatorTest.py | 200 +++++------------- specs/images/scihubator_minimal.png | Bin 23817 -> 16002 bytes specs/images/scihubator_principal.png | Bin 34921 -> 28082 bytes 3 files changed, 56 insertions(+), 144 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 3b4258e4..d75cdb07 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -18,6 +18,55 @@ class SciHubator(widget.OWWidget): """An Orange widget that lets the user select an integer value""" + #Version minimale + """ + basicURLBox = gui.widgetBox( + widget=self.controlArea, + box=u'Source', + orientation='vertical', + addSpace=False, + ) + basicURLBoxLine1 = gui.widgetBox( + widget=basicURLBox, + box=False, + orientation='horizontal', + ) + gui.lineEdit( + widget=basicURLBoxLine1, + master=self, + value='URL', + orientation='horizontal', + label=u'DOI/URL:', + labelWidth=101, + callback=self.sendButton.settingsChanged, + tooltip=( + u"The URL whose content will be imported." + ), + ) + + self.exportButton = gui.button( + widget=URLBoxCol2, + master=self, + label=u'Export List', + callback=self.exportList, + tooltip=( + u"Open a dialog for selecting a file where the URL\n" + u"list can be exported in JSON format." + ), + ) + self.importButton = gui.button( + widget=URLBoxCol2, + master=self, + label=u'Import List', + callback=self.importList, + tooltip=( + u"Open a dialog for selecting an URL list to\n" + u"import (in JSON format). URLs from this list will\n" + u"be added to those already imported." + ), + ) + """ + # ---------------------------------------------------------------------- # Widget's metadata... @@ -49,7 +98,6 @@ class SciHubator(widget.OWWidget): importURLs = Setting(True) importURLsKey = Setting(u'url') lastLocation = Setting('.') - displayAdvancedSettings = Setting(False) URL = Setting(u'') selected_int = Setting(50) @@ -67,13 +115,6 @@ def __init__(self): self.newAnnotationKey = u'' self.newAnnotationValue = u'' - self.advancedSettings = AdvancedSettings( - widget=self.controlArea, - master=self, - callback=self.int_changed, - ) - self.advancedSettings.draw() - self.infoBox = InfoBox(widget=self.controlArea) self.sendButton = SendButton( widget=self.controlArea, @@ -85,94 +126,6 @@ def __init__(self): # ---------------------------------------------------------------------- # User interface... - basicURLBox = gui.widgetBox( - widget=self.controlArea, - box=u'Source', - orientation='vertical', - addSpace=False, - ) - basicURLBoxLine1 = gui.widgetBox( - widget=basicURLBox, - box=False, - orientation='horizontal', - ) - gui.lineEdit( - widget=basicURLBoxLine1, - master=self, - value='URL', - orientation='horizontal', - label=u'DOI/URL:', - labelWidth=101, - callback=self.sendButton.settingsChanged, - tooltip=( - u"The URL whose content will be imported." - ), - ) - gui.separator(widget=basicURLBox, height=3) - optionsBox = gui.widgetBox( - widget=self.controlArea, - box=u'Options', - orientation='vertical', - addSpace=False, - ) - gui.checkBox( - widget=optionsBox, - master=self, - value='importAll', - label=u'All', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"Import URLs as annotations." - ), - ) - iBox = gui.indentedBox( - widget=optionsBox, - ) - gui.separator(widget=optionsBox, height=3) - gui.checkBox( - widget=iBox, - master=self, - value='importAbstract', - label=u'Abstract', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"Import URLs as annotations." - ), - ) - gui.separator(widget=optionsBox, height=3) - gui.checkBox( - widget=iBox, - master=self, - value='importText', - label=u'Top Level', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"Import URLs as annotations." - ), - ) - gui.separator(widget=optionsBox, height=3) - gui.checkBox( - widget=iBox, - master=self, - value='importBibliography', - label=u'Bibliography', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"Import URLs as annotations." - ), - ) - self.sendButton.draw() - self.infoBox.draw() - self.sendButton.sendIf() - - - self.advancedSettings.basicWidgets.append(basicURLBox) - self.advancedSettings.basicWidgetsAppendSeparator() - # ADVANCED GUI... # URL box @@ -207,24 +160,6 @@ def __init__(self): widget=URLBoxLine1, orientation='vertical', ) - self.moveUpButton = gui.button( - widget=URLBoxCol2, - master=self, - label=u'Move Up', - callback=self.moveUp, - tooltip=( - u"Move the selected URL upward in the list." - ), - ) - self.moveDownButton = gui.button( - widget=URLBoxCol2, - master=self, - label=u'Move Down', - callback=self.moveDown, - tooltip=( - u"Move the selected URL downward in the list." - ), - ) self.removeButton = gui.button( widget=URLBoxCol2, master=self, @@ -243,27 +178,6 @@ def __init__(self): u"Remove all URLs from the list." ), ) - self.exportButton = gui.button( - widget=URLBoxCol2, - master=self, - label=u'Export List', - callback=self.exportList, - tooltip=( - u"Open a dialog for selecting a file where the URL\n" - u"list can be exported in JSON format." - ), - ) - self.importButton = gui.button( - widget=URLBoxCol2, - master=self, - label=u'Import List', - callback=self.importList, - tooltip=( - u"Open a dialog for selecting an URL list to\n" - u"import (in JSON format). URLs from this list will\n" - u"be added to those already imported." - ), - ) URLBoxLine2 = gui.widgetBox( widget=URLBox, box=False, @@ -309,12 +223,9 @@ def __init__(self): u"Import URLs as annotations." ), ) - adviBox = gui.indentedBox( - widget=advOptionsBox, - ) gui.separator(widget=advOptionsBox, height=3) gui.checkBox( - widget=adviBox, + widget=advOptionsBox, master=self, value='importAbstract', label=u'Abstract', @@ -326,10 +237,10 @@ def __init__(self): ) gui.separator(widget=advOptionsBox, height=3) gui.checkBox( - widget=adviBox, + widget=advOptionsBox, master=self, value='importText', - label=u'Top Level ...', + label=u'Top Level Sections', labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( @@ -338,7 +249,7 @@ def __init__(self): ) gui.separator(widget=advOptionsBox, height=3) gui.checkBox( - widget=adviBox, + widget=advOptionsBox, master=self, value='importBibliography', label=u'Bibliography', @@ -359,8 +270,9 @@ def __init__(self): u"text field to the list." ), ) - self.advancedSettings.advancedWidgets.append(URLBox) - self.advancedSettings.advancedWidgetsAppendSeparator() + self.sendButton.draw() + self.infoBox.draw() + self.sendButton.sendIf() def int_changed(self): """Send the entered number on "Number" output""" diff --git a/specs/images/scihubator_minimal.png b/specs/images/scihubator_minimal.png index c98ed36d0aa3ddd413c673b1241115b31aac0407..902ca0b5121718f2a502eeb8cd3f36945bfc2220 100644 GIT binary patch literal 16002 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 N{h}yY_1P%!e*mU$1A71f literal 34921 zcmd43Wl$Ymw=N1HxQ5^wLa^ZO5IndAcXxMP3GM`UcL?sfg1fuByE~lb-QV7I&Z+%X z?H~8nz4_5iYW3=#J?9+bdBzyeSiy2KV#o-12oMku$l~9H6(ArWVIUyh&A8AiPe078j3CU7oIWwIeX`QC|HQ<=#0ng^m|3|P*n^hyF(Dv6L5K?r z{BTV@T6R%YGoo=_`mb?j*#SPMRxnK{X-yRICR zDb1N_va^`xvQ_zjX*c$!68 zNJ;63Qn!932A@m@->?qoxx3Bl@w>D%85x=X(UB!^0h}H&hDiJTe9}U##pd?5ND7

F|$|%!FnLE_a}1lfWZX%nE3dB;$q4W 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 DMG$)l From d527051f66163e0af4a5d0054197d37026582f51 Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:02:33 +0100 Subject: [PATCH 09/86] Update SCi-Hubator.rst corrections des versions de orange et textable --- specs/SCi-Hubator.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index 4b193397..e818a22d 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -7,7 +7,7 @@ Specification widget SCI-HUbator 1.1 But du projet ================= -Créer un widget pour Orange Textable (v3.1.2) permettant l'importation et l'extraction de corpus tirés de `Sci-HUB `_ +Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'extraction de corpus tirés de `Sci-HUB `_ 1.2 Aperçu des étapes ===================== @@ -59,8 +59,8 @@ Créer un widget pour Orange Textable (v3.1.2) permettant l'importation et l'ext 2.1 Dépendances =============== -* Orange 3.38 -* Orange Textable 3.1.2 +* Orange 3.38.1 +* Orange Textable 3.2.2 * sci-hub.py From 7407d50349da6fe0f3597423b582c43e78ba3c0e Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:05:32 +0100 Subject: [PATCH 10/86] Update SCi-Hubator.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout dépendance PyMuPDF --- specs/SCi-Hubator.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index e818a22d..767aa900 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -24,7 +24,7 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext .. _colin.luginbuhl@unil.ch: mailto:colin.luginbuhl@unil.ch - Specification - - extraction des données + - Extraction des données - Code - Documentation @@ -50,7 +50,7 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext .. _orsowen.chetioui@unil.ch: mailto:orsowen.chetioui@unil.ch - - Spécification + - Documentation - Code - Débuggage @@ -61,7 +61,8 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext =============== * Orange 3.38.1 * Orange Textable 3.2.2 -* sci-hub.py +* scihub.py +* PyMuPDF 1.25.4 (déjà présent pour SuperTextFiles) 2.2 Fonctionnalités minimales From 081ce4dd058b49319ac8ad1562260eb331c25f69 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Sat, 15 Mar 2025 10:09:01 +0100 Subject: [PATCH 11/86] Images plus propres --- specs/images/scihubator_minimal.png | Bin 16002 -> 19292 bytes specs/images/scihubator_principal.png | Bin 28082 -> 30991 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/specs/images/scihubator_minimal.png b/specs/images/scihubator_minimal.png index 902ca0b5121718f2a502eeb8cd3f36945bfc2220..28286d7d92518e1e6fe8dafd11a270fcad63c058 100644 GIT binary patch literal 19292 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®#l5%$7 z(bm$6XEQ?|;J=}7Zf@S4EQVE8RpoZvZVkp`EySO9mey{bn!1WTzX~A)9b1Td?bHq% zP7I^^f7%`m2zb6dQ8eI(Lf~?_tMXPg0DXyDeu`X=ZDuTXCOK9*6t z`=@?OXJ==V5zA38>j21R@$I89ay#$KsHlu<&xp&($yJ`NJfVz2q@toKypUOpnbzk> zygF<_Q?GHL0R*dlvlx)N;Sz{6FrQP`R=0(j_{R`j4^Ph%zqi0>*G741=^hKy{dZ2| z`Re(A?529(CjgSYhO(ntpyAjvy|TaGf4(=9z-Fd6f1u;KhE)Mwkn4$MV3HaM?dEu=j2coHQsZdYz&yR_@U72)Wz$!_&o|Oj93`4?9KV!Nj6xs(z@Oh zj@@*S)VS|!+x6K_0t*C5Hj$&=h?doERU*af+ANkqvpr1UUQG{rd4G2km6FmAT-TF% zQa^o=)2^D+?xY}atjE`Dc6&7%x|q+N9aU;oG0j@?>^ku%C@3HkaYq+w*RJ0+2>YWx zK48(QXdU7E<&|eNi6PHaSdjzQvO9*36*|wmK9D+a(D=}w!smXRax!gEG*qN3fJ(&O z3P1@WBI0Xy_A@{KLmc9{+1XiZQ$Av1;%Fw_6kyMT>7p+lj{<-;^$JV8goK1L^RX{{ z?&m)tJ=oi0c^%|oyh6Y=2E@v6>6h>4&!1o7<9A2XD1jZfM=88_fCZ|Rn`1F(Rv7*I zjCgvmkP6(0RlXvn9JzQI%JYMTf&IDK7e+I1aBz#8o1GO_Ge0#7;&>a3y3lD=3uPoE zIf+2QYeT7Z0)>M1Y5EK=K0SNl~VzZCK!Tepee|`u7X9LAvXi!jw zZll+vB}a|J)-U&idhtfDJ2hatW@ct(rbA>0)mXI3dh>OzY-YosZCBchU5*TKsNf5o2FRlJ+Dvo59aGnw?_N{FmpTGZqtO;w|#g5%ZLPDJ16&Wf5(JxHEUko z)<)-Px(^^SPRMoPXyNU3`u9=X{m*(;8a(TLiT+(i2AhLvFu?s~fx-yh-b=Av=aS>Wyz13*=rdPyc; zp#}Q^KA9BWtD2dln3x#nSDn9nU*K`sy=iXVfI`(X#88Mm4h4U_&-06m!vSuWv-5?= zgnF(b1%SSJDh1uOw;sT@>(0hCafo7;cHf)Cz3}ZhYcBs17S?Er6f+}_vww+0`~C+e zjCdGvU!^wZFpeS^jCuM3*RL56J@slk3RdIZ#YAXBnp`qBy><;-(Mvn_l#~=?e74QV z=sFNC5?Qgm{Lbop7cB@B4sE#d1N75zd0effn?Yb+LtH=27_05VgP0%(c>m1B|S$()CUx+Yhw=|8ekAKHTxhuF`X`>0hZB! zQML*|?RUkjZrO6G3yq`2MLj^Liy0fQLk3>(@bGN#&3{)Qm!ZS}ZanNa;KVWMRDuN_ zZlfG`#sPR@Ladm5S^cxU*!y9M;1tlTNsmARDAccPW}kp#o+#9w7`@jVLck%uGwF>N z1oSl?vjN-y-vyybf6|k007^a@4Rf{5Cmkf-TDC+J!#IE*%>uMSZ>oR*Q!DJ#r>3)2 z%=YWOuerGJJ`4`NBO@nIV7E}w;n_dcQ)}>WZRi1}y{&))5Q2zNQ>n9nON)l^zFhBd zSgO}G&Es_$OcMswCk8PwYE!0U)MT|i)zHw8h?p1)q#IMENJkcs@>I`ryhKiD!`dET z-xvYxQqEQM?TVtpz`+p*0FcSuD22lcpT}vpGq2nGV$K zxcAwZs(OP57Y3z_9{JQl1;AU~`OYmT zX&ISJ01`ZI_9_VlypjMm=vU4p@OyG=*E-dkADw7i8}xl;Z|&&7ARs2$5w1&*pC zTQ>37tI}>w3b>1H09*IJ=ZXOOmEq1PbI!VPNv}%lQMCXET5FkRyFXhUSMRr^F_R{* z`b8^?e|3A?O?o`$>sKi^H@7rXfAvJ2HxJXJ1(*1~yStXw>+@8VwM0np5gxdHwj&ox zKc_4KJL5V#o8pgVi^;Ue$VltWfaK(4Sv$L9hU&hVJxhNdj@r(#sXZsacBIj%0|SP|Pd(AzpgQ6!g%Cjz zOk}cjy_c_^`23ZQ_1PyePX68z&Ui3lV= zne%>^m=s50YNhG0rXR9fJZ@Mt*U`Qb5e~APKIMCfok~n%Bbze@&f-ee(pJfQ`XJgzUUpH8cEePpB zSFV4NYS|B8!o_yu?GThN(l+>m&3jjxBOCWavQp1{2Gr-d&?lc<r`@g&;G2@fmv zi7{qvg{O>#A^QRUF)>w*SC5|$!X(=c#IC8Q9?`vg=sg$&&Lis*B{TxY6!nQ39Pn=xW>+ zd}Aa;Lc&l4o70Rod)V()r>e234Sr|%9Nib5$*)m*mbbMCIR=ayhJ0|~l{s>A?f<2mO%SCR)s!bHboDH z@b2s3=tG~$N)5?o;{CI`Ywxc4U6ExB>BXHLDeLOy-8FGDrKh%%aRh?|TDK4|HZ5FC zME3)Svgr)To08x9QNOLiupcK?Mahd&>E&IW7T>t}n9 ztx)kMKZj}FRyL_f?<-%ujWk#?X>Xa*%{4CFVWDWM#sa6-Y0qFH1(q<_E6y)e&n{Oa zPPK6#)jO4dNS0EjlQuY9q$J83Ah!c&RI{z8D-1&MQTJ4JAQ|YXG zWN&KUi-Q9Bp7S}E{i5gG%Jy}~FRIzrLZB%*tMZ=TH45otG*Aua5eZ^{QeBxlyxGw) zl`_3LR?fF4A)yazv(7AWU545Ahet01JTQy83!sC#QycJ;3SD0L+hQYK5m!U7x!$ z2|xju#(w&GxbT3-)Y{he>g7wDyXHl}<18&@4Gj(5R)`>LHDZYXaLbS#UY11UOX2PL zK^`^h;n*MG^lx!XG|;E!Es_sl^hE)nEF|=adj&t5_B|3OC+AaGSS(~k2jON*j*)zI zR>yY7$tqiN1XMy&YHA53L>f0mC8b>T(roT!?y(>5gQBA`LvS-qr6eSpK&M%|oYT%o z@H8cu$dz%Q1Tj%XNBd?w)!E@+4Fw1y9heG|`^|`x!_z1?+pGwv-yUg+CIw+-s2!n4 zpCV>D#l@~;zAJcozb0&Uc<7QIwTCN)S}RtW+17(`sk?!% ze0WBYIaMm7+ZbP2J4QA*;cr(?vYfZKwV^{E<;kj(t#k%++Z~-_7esYs++$`*)sQ89 zRp>!rA#lMo8kLqO}zOZhfiZwESMZ#fR0#Han=O+Uq(fe{cAbX7Cm4 z(|ON><~LbmFql>^Ugr~X2|?$pewB>a1(z^-NKnVXsLYNJ=oQzl_GZHfF% z!b|;&?_$Rbek{E!#R(gAXfZlYKdO(24<<9NRL_RSF)q1HtCSwTjq2b?22A*ie_z zUJ<*|Ih#D5@sOKFvGm_KyqRA=HQ)Pn@1dhf4j=I}RZ8tSK}~cNVlh1dwvggi4E}yS zTn@Rm_6W8c$scgfUSVR2WFb%)%F0u;S?l2%OT`}lI+}H(M-7dio3&k=?cV@`FZvzU zlK}z=0VWB|zFLry)Czb3Hw>$`1)Mp|cP6 z%@4BC$7f`=s`LqdAD@v@#Tw>FEwAjs?H6nfEjm*6EeK7|3YQTMBb&5D4_KrY1ewyl zwo8ncax|V?X}i2nPUW(!d^uf>a33VFURrKz1Y0rMV)=zD@UCXuJk1~{MfrAxwP7+o zI2jqWpRgx-H1zcQ1{@`t#)YLw@2Kem$()mhk#S`tP^s}K@Rz-`@|E^o1}%*!a;_zvYL1%iDVWu~@WhCtbfT7e1> z!BRF1udQykaXz04Q3NijVDmS8p8(TVQha99)^B>@>74-e+PTm!BgH4j8aYpmS%Kh} zyuAD~A52+mYwOn5)|bS@UP{gsHHnjZPJsDtV{fknk{H4yBrjTsIlS8)s^#5Xs{adj6%eq@N-bx8mq~2X;Ltc5LrkHKZL2qP#c_*F_`=n*IZyLjx?M6ODKMrLLv zuxU{x06H5|_9?IBnn^`tKP{aDJo%LtP?Jz}qV!vRD7uKhcy) zkx`R8hedge1v}^25)#B9gkFig*Kv7D3tPXgyRK}wAE2@nB1o34;TR{+pt46RQ|S!rS%GX+DXe#%A>_hQ!lPOvhMe|IFo^1x@Tg8082EbTyIj zK4ciI-(G9>;ztU9b62qa4s-R0*`&7_h8lX@a%fzg*m0!f?W-Ywxd!7pp7ZSM)W)BK z<^lpzO;x>(kHGvB-zU+Z;QTW<-w9TCB#Zn@UGfliM_?7QN`s33BIf|#*Qk&6duEnm z*#6jFtvsm=MkXa6eMQcV{YS25qn}7~ed^X^T#zG=xQbf0e`C(iPFDvv*(p;T#Y`1y zjdr;@#=%H0hW}s?A_(kE5EM^Mq#kBRZp?ZxNzS_rZD7N-3-Y8y^QhA@JLxs{+J1k$ zY(n&qVnUKC-e<;&r#pcm-OY50lIq%wYT3;*tUG)^IVCeS`pK3~eCXHJY%ke11-I-~ zvf&+Z78_15`sK!^pb}!lC$6U|-qASt(3Oz;2gr20VP0BN$ z!NY-PEMX7KZf5di`+_)2aSo*cyXrSP3N(5nJJWGOj#aImycw?J8O#dK>M-lH`^%fu zJH$O(fj%c$Nc-zrb7ZmyspRHW`2{BLmHKHOyty1~tlL|}f`zzOFTxCXoQ*gDpvSns z@NAFM4r5Mtq=wvfD-?`)CwPJg>}^Q=&Vn}Tu|rJ9(+SAs*wd6md#+0HObA>PEO5?` zcFOL`HiwYoUU(l2C+QTRvRZA++4ZBKFcRY3X`VfUi5fGnU&c2uG(0*zZEap!#uImN zV6&R37~^?wo#6Wd2OSU3b*cl1yNUs}_0O5T?e9BW+lhVjYCk_XZC<7CKhRtBds2X zVdV@kt1}1F|nKNl4^_@u|&d90Y zjKUv#`ae7qhD*GAw+s~R_B~R~8I{bJp}1chSA$@S zlfYHU-);9KE>CIN^SivA`vb4OI>$|{UHQ}MEb->OI7{^+EIL>)X_pk%RL%S;MkZdW8BHy4iTawoK2SX%JYgModLWkx+m-e?<&*dzR-~QlHs!896G4E zcE_P*uCG{_vfLBEt9EaYr=JV&@~DIkek+Z7F8)C3fyQVw{E0~Ih!k80ggsy|h?@ng zi03;LYH|AfLN@ja?}6ZtHz%%4yi8oeOWY0Oo;>EVl?NxHrNit2Q)q>Oi(AA2RYwS$ z;)wL(wuci6D!YzR_vil1+r#G}1n0(=Q1{MGtB<90{bspI#TKwZvv|#V=jqY4F&M=- z{o8x3!~&8>iYb^6Cc&2u>%It99w*HQtC~z~F-=)&+$O_zsjDBLcMl-*YxDcdMtDni zPwEAtvece%)=V7d?9bLXukHNde6q;)c&>{#eIj}nqC}kJ@H-~tR+CAhOeYHX<>KfU zCDuApa=Nm^E*)gu<_~|xCIczT^{Lc+%iZ;3xEQ|fc^?y4s+-9LOTLIuB7{1jA1@ap zWmPJk;JzUNH*Fm^N0+KyokVTmGGE~0^9J1JDIp^KLh$Yq??XKn9QX?N?DNR>Ra>D%W(rU86|!4h9x@pgNHp}%H~r}N3KI1Wpl z1;ekFymxo=Xp(ymly}1PZ)tZ_tfc=JPa{#f z2p{Zv{04}*SDuX@O?i7u+z3hrs~t0db{)A1&kF#hX_dd* zY#_7%nSf$7dN%01mZn_h2dmkt2q237==Ph)Q~b?;u88lndY7ldps1+0fBQ<F>65fLJnvCu({=C=Lgck$zEyZ_qxJySkL18naX^%d}yGuxk)A2#oMUosv(2FOY8pp@+ z3550Dq-!kq21`FkiM6KjbrE21XHHxOUak{zf`SR1m~>aAKac=e%)!CZX`i=iF#W<4^FZY&zv>W;7zHf5?I3a!W1`9&alKn!k%& zN{N0|{1cv>C^`G{*3XE}OwN(0Z4p+uYA_{Hl5!*Jh-0{!Hmv#dNw)~E>TeVak_3P% zjLRE@!SiMS-?(G?P|vC=?{z3W80y4i68TtSb#!5|lq+ z(!4b;#RI%afB%kT66C-8k2-oeiXw18x&bIx2VA$gtLB%uxSc?{?J-gXxFp8Yan!`DVqtBR~mix80?SugaV%&iCJww*L&~U(yUiH1tbBST|kqToK77D z1dROatE=HDDWUqf@qNb0UooqFo;Cw{g_IOIC#Um06nG#{1UQcp^74(V7_nr>2PMDb ze;ytl)=&_T4_n#Y&1WE0gxdnbc0f*H6&uc{pEm%LPj#l~1jUblZ|pUha|00J^9TyV zNr_}jkm07FQG^pi^3w+<1(HtvA4<8Y3LiDBA z%U8S6?+@y)Hhh{_Wed(_5$Ur-NEN|8uRWiw2=K^s3}Lv`h(6Csl3vtFV?+zV>+msY zFxtH}LMH#1dOZf|%po~>*Yf-mtWfSnlX$)y8>toh!I@{svzwelmsP$|uS82|U5WF; zhufQC7deHz$u|IDwQLVw&0!^tcl;7T;>Wc+FEkW3_MB$3tH1nca4}eu%Q}?zu)fRh z5sz0o?BdqHu)9zmu#wcDKNygeWNY2olPVy4#^M=|TOWh6aFLUAwQSa1r;2cxyc0w} zYx{vOk3X$Fb>MK-839Z{z-4)53s0ewGH?!CtA1MsyU=*XS8FwuPxJtvXYSeGUVk%H zuMdB4ktZfO$03xt=+g{N7Ln>wbm7*jsq&8_ppop_aMBYuzaV-`#Pk9aEqx+tj{3X< zy+UVi{2VXulJ5sS8md{4H}g-Iv9(;mvndY4C*u7vpfBvM@!}RWhS^|2D-8^6_kauz zRxiP|fEz=WMkudnsD&%7>ZwRIsU5+m=GA?{u2GTvxLL$*ImKnOS>CyUg3jRD9PxQ6 zhWQ4UEH%jnDbHbvK&sax{w!Go3&`2=MNIqSVDvp0N~!DUbQf!PdQ`PtpuFTe_z=O% zb=Ftihd?QB&)%c*itVdpz^tF1>I8%n^L-A}N5$y#@5@5n@IyKQ^qNL8$JPd8@hf zcwCdfoJ_pEt3+)~l_OtgJq{V2z8F#sP|1r~(s$`JxTIR7ZAq=blv0fy5HvG+7i`4w z9|hx`GAG)V>5C%q;!@8?Q>D@lB?L+8nl&KyZw9S$}|1Qy4yC<|Q&1o#T=!n|H6PZsUMrwvqm|Y>FNW z+R+NrfW7=ajd&EDY+~)9>x4O+s(Fve`A3hV#&s}kw&I@a@vF<*c^fh}&u0D`QF|$@bx5sh6+MQjLXMvM8fzN66Dv0BgZ zk%Yi`Z7T(}UF@yi5L1knl8Jh^{66~Um@AkXP%GiLa8^8p)-j|9X zBfF@jtN+*JgwTQ$gCg9j*Nmf>7(C#t0d+K5-XNgHVez*^#z=ulBLx&F0EH}^Du#on zf|;A$(1!-|BZU!!h;%N4&ai(0BFyLh1nQ$gOEeLR&vY+{9bRt@KKmN744r$Xk$E_V z3n-Dh>$42IwQeJ0W1STt=3wi6`6z{%K`$mnI3NA#GBY5qc-RDs_AY<2+|$D9e0-~y z@~J=9$YgvL3c2E@PctYuNbCiW?BY*^i=Ljky3AcLqQ$DWp0eXjvyl0+ z2{5_JvrUPmy9ERO`q8CiFKNT%$F5cOIusL z)`{V<>1b6^V~#Nj4go-+<$i1k&c=hx!U^~DVX^V9`#Dg zQ1LH0_&;^o|7Xtq&t&~y9g)USJd0ZA>)j<~W$Ozez}W!N35BpA%rQL)Sy>7emgAb( zKp=kx4Z>X0gRyaTZba!TEq2xtcO&wOam+|u%G{%{)12jEhu1{TNW2*_8s)IFcG7-S zk>a+S*xv6e_7)Ai7NS3;U4&5MT8Hfxj3mgyq1tB`Gw-B^eJy0diA=|RxEDfQ7}o1F zzFAec{RxB=ko;!e1Z{4e9M&9Y6VsOlY+0}{x{XHGMMl(bW4uy~_)!3Va<^b+Led$q zv|%!%#KRjsC^cs4vEaf%b=L+IW%d8MQ^Hd#qI876?HmgB<$b@Qp3R6STBPv=?))af zW#*M}<9woVIoWeW)Qo#il2Xd6Sw<*NR|y(Pwt5Uq_cO7<%d3S+wktDuuPaWAd8qi_ zG=qzUW5qmQI==A7ze#pHmLyN*OKut6=7el3nd@V}$bjMw{$z_N9eQ97ST6l-Wy)kc= zhW4jko@M#{Ctt*npY5HNnBC&d`=B;p*Ug-*ro10fi*)d6(n&vpJuT8eFYWR@L?Fq6 z%qqqb{ajLG#9i=tabpu5vgs&tHCd7{x_S3*R98d2M z>7DNf*dr?sPY_6sdTI=f5*UmK1w`aXV0Qys)q_?xG!^xM?8&V~wT(IP2nVNOZ;8NT zu~SdnL)S1`VzJ{jq1@yXWJL`0&OGkbH!tH>{o?%bY?>!=WaPZ=>L?AU>lfON5Msgw#(H8J-VL8AqdtMUmc?zva zk?078)p`9M(WZ-%XQpX&{i9~LwSkBu z=VMd1V_=n}-cLy*gwyUx$TC&#HFgd+a*8Oh!icYt{GJ-{G(lNWhwI#xw3u$|E&dKU zErFCi*Ws7O7C%0#WONLq)Ll-MDm%m73|-w;DxnC``6`v4-DL6~V*_E0_`2z%)|Nv^ zBCYb?3B?T)mz8>OwtRy~=dHNe{0|hO)Ffd&f68d^1jWZNk8Y|y=VOi1ceg%du8SuO zNz8<~M~g4bt#E~mT;4D-^bOaFf1&>!6E0@r;J^l)9YR7zM$yM|eE^8HCtiq(iYfp_ zkY`n$M5I(y2tbr0HFW_((wMfKk(fvT6xmMH2M1uHa$+I_VcTu4S7U!v7Xg6vzsu48 zg=_#iK1N;t3PAjJVH|}Q=!%^Wbbxq5kp&)5S}i0b1YoZyJ1)=?7#v(z2uaV#7@Hvz z<-&ylYSG8st4pw1s-|7c8IrpU?<=8Bu|#)_dpgd`D_kvA9fFC1*2&(L?ct>f&iL0$ zdwX|bB)aDH4Su_t#RL6b!HfO6cBA*u+mG zH)_GO@~xwBve21A3)22Hu9htY&Lk=QF*7b3vP4A|^^?Y$QG$lpIv=-oJHK(uZg)+4 zP$cJJTT|>T2DaFm8=s5e{ZL)T1!PLjhMqs%n8;jlx(!eM;W<8gkr>TLHIe6rkqlIDcl-2C43Z1jzj$&<-I&3pa}_ChH&Q|hJinWN(*wcTkz zs+?Dwoi<$H>noDibqgT_DGa?XY(B*gu8A=w{V2mq*dR}NXRpxtmVJQ*a?|FQI?1n` zoy4o)E9x;^x5uo?F3tIPDw&qsmUUTNPO*PDnuWP8X>lY=`vtR?s&CH+GQKhssb>y9 z(9$uwuSgd0o(q;`s&9?PxY`wxbKII-24m=61&H1#GR{wxq+cB#p-Fh?;cGfstxepl z;9l*DIL(lnbeJG}xMD;Y-Wv_vGtgfi+mex|F80I`tV~~f-cOf(Oc+qEH?49WyO;Xf zf<~Zuyrx?_NpSbf6rCYw!T1ecIkVpCa1&PIGbNd8k)`%W(tDIK8_3I(y+m)9k|JgbQid zoDzDe57WiDh3xoo)^5>w2x{nygj$*xK$>zl%f)$1s>+I;6+1e8VX@+pC&8w0I4mV* zyx2%~I!3pBRd~X-@x&`x+hdSD((i75aU#A{{AgFUG(Ku7f$By%v#KkwNyjs{7K-TI zYFr8h)>z^4^)-r=Qg7~?`{w&-wmBnjF6GRdj6IqSIOC$4vVx7?;+CVyK7KfrPNTV^ z#^Z?yUh^N#7DDYhTKFojuT~Mlv+juC1eXvbxyzX%71CyLseEu_DUrR?c4u)8 z#~JsAOd|(zUiq^rvT=(1F8=(@l?p}g`j(b6yo2L-#)WNHwaPxqa8BsPgS7RrDC49Y zysqfD(WVA^;|?~CoPSLoN?Lp|djR5R{RXeAggHMw+$IGkMiobOrKvx3l(Ft@scg(z zCzXaRG-|dU(RcC}ha)x;X6Pr@#Cfw4a2Y|2flpv0jg7I@xr~LlomvFU2{FdoqEIFk z!+t_GXm&pcyWnug-1^vJ+-G{k$ti~jG4%80a0L;+!pfCF zMhqc&Vk_Sb7~+GTLJZztXf8wsA+KCt?|cc7F}hgyd;@{)zgI3;4T*@!SkCyggc{;E z*m33I@Fp+STtZEPy++o-ptG{YY}sxfG1Spi+Y9?{$4@c0%O=#}T0qQ+!EtKEe0+Lo zl;I$(u@Q(-VpUya5aH_kTrT@ajH6k|x#*F`YzuVydnfVM3abfi4G#szSac6(8CI7j z8y$b^<5>U=#!DQ0#X>|b6st{Zd>Iw1`|J!?x`S70W;!jp=v|21!EVmgWHB$Ho}YoE z>ssx@vcL}WwlDlkwQ4Td#@V+eM1*;KJ*}_w>4}u%7VTcMc`f6dPkmF1>cCYr#=iR@ zYIATyz{E{%H+ElR0Lm;`%X=84t|QZbRqhJEHdPn{m3 zIkKJai(JU@QA65fcAO4H^vjpOJ2aJr?TbK;R#|z}k;&cyZ@Px;*{a{C*FX}Mk1AcS zss&sQxh<@C3_*%uIQ+BD{@>~Sf0uaZY+UlQCTaX%X?ssvAUEQrEx<|3bFHmWeiL56 z^`}F9kkrFFB(b>R)r=gUfGS2f0zYav2p#8H586Gpstqtle$bm~_V4RiT-gcIO(==Z zQ%hdIK-;MFOfd0hi>W!;mezh=q1C}Ho5DtT3LiG^T)SJT8`POhj0{6bLj2Y4^CU(G z_@_SpK#WfBNs-L!aa796?lNmUKZ|{0>zY{YxhD_TMBjHzhOn_|%9?HXU)!917x5+-_H@^l$jS{zNt`mRpg-4!!G4hOPwqP{#{9&-W%T4toe_nDchx~Y%>gSLH&1CaE07_u zJ4e6HvFolJw57DHWtKdd(9WKxS9N_7-|KMwzRnSQo8YoWX4r0SEE==+@wL^V^V1+z zZFm8lutpQc#Q=tnST8t~P9g+HkJt?DP_qs)_Kxa*s{UVmFe=WkNdyZ6!tb@16SZ<# z7Hu^s=uNJ?W~Sc9m&do5@OKrE24+=N8!** z>W)shbfMJiJ3*R?yyJv)N0R-QS2gQcGz>cYF4~iH#@}a1y*R8cJXDtN0n@f|4i!;I3KfzO~&U39Gmb%?!QX2QubV;lI zoTlTdlUX7pjEe7~QN1`x!l9+7#luTmbrKoEeU?2vy`Wy_LEPh6JIt=^tE2!*ic4;a zCCMr2uSQ>jFwSuWUy9y>JO%Lll2>JQPe!tTl$kF(u8l;t;SZMz^G5M&Hx1E0MoX9S z*p;`Y;k~74zE%{9SGMReK=;7Ah zoqFk|3HXySR=ToA)lg{-cx_KA&KPs)gU-I&1^*uEk*pVj-OsLY=I}Dc?AiTvWj^GB zv*;?9yNbjHE8g7NlQ{02!WD3!qz!5ENHV?>yNGz``0$ohm7XPj){K3bAhhnBMf(R| zkD0w083|#JNf?{~{HOa9X6S+2*ZcAY(vA%DJ$Lpx%b^pk?!nWpxcKwl3^v`(P|Yp3 z*@ZMjis69`%PAGdK<^!$AC}y{G~XDCLcL?%3739s;K&e{ZEJ_A-rL9HaK}yftF101 z&uJEn(~a-_RWQT{Ia%)mK5^Wx(V?cL{Q`WjJ$pnH3B)pGb)44n+L*LWjt+LWx^?_@ z4d*tq!P?&32FX`oSt?G*5Yrt^hEe#_=%^^4G4r;8frIf7Tp*Pl@a0R*K4f2{qJ=;` z5lh5KRGyF(jb$gXI&AlG} z-VOJka=At3ut)4>clj*8U>$g}N09N;+{GULHc7@N7451bBZqM%_7_*o%ZPNon89!F z|MhbiX9*ClUz!d&jX`0B?gjxeN1`krwW7#crT2#Wnj%p2w6(Q`>-VwC=$FwjyDOQm zXC_eS4z#VVuFk4~E-x=1i+zAvA?zT21bRhfF(jZQ0Qd%;j-P5lI$d;iKeH75e|&)R zPrj~QNB2eK=HCO_HE%RB13K&9OwY^^0A)ryXns{yVBia9$v||9)7P{SWTY3u%KuTB zJza89{-3n~|D)tSebDn__A-lkm)rI0*^Qj}PN0@x@|Ol>#+Bx8>-wSsxcr*qM?7wfG{ypa+hdP^+xWo7eA^&-)Gcr8&C)zqXz#&G* z1;48I&179t$K+pa;bwN!|DV0R-BehA%`dc{C#G$Cehxbfi=i8daufb}7MRxjrv=Vi4;xh{-^i&=I z*?H{k_m>(LE&4Lj$#BJh`QjqWV%;vs<0y;!$AlDP1u_IK_s%Ou^9SYKry>s8zzzBq z40_>pp`qW8>I-=$=nKAe<5b2msd|D8&X93hMYPJg5vScxts8A8I;q3fZJV#Q{~#=T z>GzaO@yyQd_c9HS=F1}x8tm$xLHXX@Ko-0O9_P!0FoZ_$cx-SlBRC&B{In#p4NqN7 zvFM%4gk?<@uox>@lp3HXH=ZjyoWU}E_B1cL1X`-212m?na$Z$X&&rnZUu**hMYSgCCqFv9dm!`4&>J6X#DLT!_{7e#^Ph;Qy2TdkMYmX@F-BD~oWHM3)s9k}Z=fc_f${SFxY z4XL6RzPjUkw&Y{+>9AbA{xhr>QUrKiGxj6IzzEc-mQbv%^96^vb`K6fa@Yt62m@17 zmxfqPx07E`c6=Y5DO`MIttJwLAq-B z{+r@!v53D0I)s#e-l~7KT0t`TrVaha>wr>aLI$yGFw1l+5lu3r=`9O^|1L4LsdK_4 zYA2&oYsAZQgL}>;U}Ze^mBHcJ7lEV|T?`HlKB9kWIlxnW5$VsV%HboUS?8S#ONR^n z+!0(uHt5O!$w&B(@$|Bmt{torZ>n zI5XT}k=xpBYce$WZ6rnE6fTzY!AOfh;h4ceO|A56AFXmPPw zy`@Z7tnd%CuIw=Vul_YG)?lhXMvHNc!{zapbVc;hWV(P0- ztQ>2{7i&j=4YI~1vr_uuz7b49#hP4&-)po{^!1AHJYPC`|0?*h;5$q}t2T};VR~$m zLo5wL%8A*|QMPM!TZaWt135}G7W}r1(U??+=vB3#gVi1&Fp2JJE3B_Y!vm0{?qE4% zt(*wizd?<}`6%Dt#+Sy+gH}h8X1Ed*$bm3ZGZl_vAgUlSkFWg0W(+CAT^?v%^IK2& ztLe3InyN*Lq^wcPF z?wSr}#h)~tQ|0Os`eV*mhAk|Y)U;!p=l&BZT{G#0He4(Bel z0XfE@3|6Qc)BL;1IjfmI;g^2;!mlMjn7?9^@iqjJiBB^oha;~Gqq7zJmA#dDYMN2p z9MLi{lsIYa1&db$eM$p;La^#cfTmuDe>T!*TZ!a5C=5V#+B`R3h6Sj7L+?;VU?<~Y zlFu8P*YO|hkc7)I;Qn=^HYg&PodDz zJ|S%C2?q4b4stPfBHP+drMuE$JJ(<2F2qtYEY-V}iB1R$ICHUd6tga^%h$Z&d-cYsb^2=FrrixS2?(urmtFbrYk;lY&Y^!9J!dDEaJ_UT z`MmsQ#?^4+!g!f7x1;s!s|>R7u56yzm|(+=tr<&V8Hv_2I$Dy;_McFQt73#S2OOym z=6M9JPW*j}WmY>~jeN&2&dubxB0H8!&tr{DyXA~#f#!*hSGpA%oMMvNj>f2k(*Dzz zW*u(+S(sx}&{N%mtGt;76A?#8={vH_@<%EoUMz;~m%s_)fVnp(Jm9r7l$O3NWGADz z!~3fDW=xdP(;0OU6`r8+@Ndcx4ijKIbq%p$nC_E7&G*F`1P~AZvlR%pMl86YW(wK- zz-GRmpxn0p)c9si-Ty}*FQOr>NpW(w)Hesf97~ba`E9&;w|dg2l>vx_&YU^I z>e$Mi1)cUi$&WSIfCEF!Z|M16 zHC=a}IfT9+&D#2$7WbB+}DaN{=LR_3<=j%~b(VpX9nI~g#nfXSU$`x~ zO*fJ96$mkEE;IcZG(n3l1sW|y=l9`iTTd{u41(p}qpL(};g1rpDr;zJ<~dOW>v46} zod}~8hhiw#onr40gO+(31x&6(y?$Pkh%&`}1Jx8c>QTxxa`rX`xeX4?$NRG>l``~j>NlVzL5o!Jalgl(;5@QnULqvF-&zkP}hnW9SVUYlBL^-V~d*lYBEAp zGdZ2!Vqirx*SWNR<~OzciD~2?3wflv?a!AONQ0Jj`|jVI@&8(XmZkD5nnx(Ua;3!v6nS34&Z7*9+dmu3?l zy+roT*3?oW;>ahBzA8ZQq=GPRX;xSMbka(Lh&YM$oNX9!{4}pkx9aNeo{azu+#oL> z#oS7lP1Xn=jBB9kl(G&8F)?J%Kbm}F`OPk6GY{e?p!lwF z1VdA`sOn#Ikghqdg8o%{L`yf7mb!Mnic}*)Y+seUOi78Ee1xK~=C^o%Rzbti2uomH zQ9)s+qE~tQfY>{=SMXO24T&O(Qqp`wG4o=5k=9bTgY>r-H#&ZP$S2-Ley8rJIMstN z#m=$mm}adkL#1p9f63N+3rtcNv&E8Fy2aL^jsd6ym13$4fsj?+&Qs0f*f(5V$re+^ zOE%ngJ^1q@@6nfqxkGAoQ}G?K4PDq^3jXglgTM9&C|jRVGNMf%s^ZxaWE;Bm@&$5| zOvEY9=eu8&WumBt2cRlR6V7cv09oohNj+A8)9y4J(fT#=;7|XeDUs=fSq-VtSv3hm zrw3{NRKTX%m_ovMl)|W9`RLTSaB)x9LEjqE>Sn5?KN(__a+;R05ssvD z6$;>ZDTtCXM6EGIiy9G*d5KaxOMXmjBRZ_Y*n1P4gx`#i<0PO0d8Rv z`}dte2Gusy)TEZWjBz}Hr1(4M{ zHsg!MyjLa{1wkQH_-kV2x|Mp$Ob53tcU@#$DeX%5l zowDD1+eEka>pB5WGA%_O`)(Er80?c*a14?&r?_vKU>po~EpBPy%!X(Cnml>y`lP&S zf1a0;MZR}CP$;q>5wyMJ(O}!HIx(z$Po@cLqR$_#5ay#(NhO>rd!*`zy zC6jyYV?Ly5IR5O0fpx**?&Re>qT9b1jImk`$|2l;_SsXoG7n^UMiOM?70$M``Kh*o zfSA$Zd~{y{%#uxxW9M9JF{i3mF({oSr;0bb6tR)@nH_QXaf9>o&V+S0@Q+?kDq@3} z##c*XL&#wRp3!P<dTC+Vj8VNwN&zo35_L+jBo9XZewT#A7+d-*hVOc+p#jz6A+U zGpVN@+di4io8jU*fsNQQPmF?&YzBz!^#odN8DS~DY>bAhjpf^OsG)cPL^Xru0!T6S-wqKtSXttXt>i@^4lBnpnDtaO3v*cvdi(# z-rp)k^eh)934-UdDw53xruC+E@yvo6EWNaZ>#EDTh)S(l{nocXlIC((`hnLk&uv)CE~h8c8-g$G#`!CRw4NOB`?M3 zu*QX}(wPJF+z2hYJr*`zq4wxvD^#G2$&;|$^GG+uBn`1GD!7zcL#xOz`NP=)Vc>z} zHQBwwG7L&3EG~bvejFc?rkZ-?LoA2I&|lTr_M_NZnifrZ>GdXSR7nun~gp zV;{k1d?(CW|Cxukpj%#I*2Zk2`nA|8a#l@Nxz@ii&6f_=ToJn?f(`C}-!Wh-?eXr& zSgkIOd{)l5IEnh#DBo{5#_-jS2uGPmeq-rpwiL*heueII8zI}NRZDBNaQD-iFQH`M zPmQ0id1{J96y2Y*I|V8edX;9lM|aC@tQG#wt1WWOCDvYlX4q+R$+yDd-R$rlkI_}! zDWbI=RY4d9-8;PgLL#z|*uOgL4|>OluFMLl zyLffu64*qPd|h|ew(2`sTDW0AJn>?2>_APWa$hKOf%BA)E%CoD>`RS*{3WpgJ=>YW zD$p1>2kF`DU5>$$F{1F`j>Iqh?g7I6RSON6Hy_YkT;IqYk>8lV?arP3vlm!i@YIEH zy~H`xD+-%>sNh_iDX32?cbnZDk$Q=^s(`@X*9Y^xNQ?ytC7f&)8P#UKtTOg>PAq{&SZAC zWcr!#ZA#KR=3p9v?ax|*21 zaoT=P*tp-e{OMO6=jRU|$xSi>`ZJbQJ{CBw*qpK1H$IE5+l^$t7e zei^(>`dqEK@byCI-{G9mm4P?d^g)8`pAd6$VMlb+Jm&wzn_)osd$sIQ)Bbc|QAx)! z{lneAU($cKxB%J0*Fx|}QfuzxoV`o)-}4c5@&Xs+O5~aMTv&0C&<`}(|3_JP`^16` z-;m|m=W|5;d?`QY{Kx$|AJ>@c(CqWftdbQ*;Vv31j4u#+M3n2qhkZDNLH9Nm%Ckgc ztlticydG;L8gx}0KJ;$bq4HkXoAa&>=`VC6LhY(4qTP?wtP@_&lIXJldl$)E&m zPDzD^>xn3ezl6vxcAKW5u2iX9Nt=g$Nru*?O%yn<7OhiV0(mO7GtpPbnoS)^v ze%5Rq;*{RyJS^aq(;c~26R1^ZMb~qsu)4ln1iaa4OX<~^-P)J}C%+R|gM+H90rJYR z9Fq4mY07JxO|#h#?NpR|bEcHoO>u6Z2vn?W$woz}9~iyU#HFY$aTyj^oUKvC)tMMA zEeuU~%{k}XpVQlthg)0=r=i_%JOlWpfPY|Gj_uc(-BjmkQCMtWToF))>ng9;ywk&1 zA{^?!deicDL9eBfL>}@PgWhLHO* zw^LK4d|nKt&tdD5G{__O3QmwwJsUgABFT z0zs!AD8ZY!@1F8yx%L?g_2^QM-0nrKsBvB){NH-2cwDl} zKod7Soa~<+GnR~>n4z+QGlyZvA~E{B0Mpni^gH^Gtk6xT9cF7=$nMq<3=a=tLk%wR zSs%i@*h)V)nu~3~?HdLsTPf74$>vuaiW2HK0 zrL?7?ZqIb8AV6Y?OReLbHKocvNx&7mQCcte=%b-~I;sFA8<5j^m0B&y@&&oH<+@lT^@?#X#ngWn*BB`n>I=}}lskFH%X{SV9TA7W0l!|5 z7}&|9=wWMM8Kd4`{u4pXlg3n9L_v|1VkJTbOC9FL)Yi=Z&R3cvZJ|tB{d*1)g*3vx z&btBKKjp@KP@veqxr3+@2#oB1cUOPuuR1JeEbNrO#Ur$|lwqL~mZIM!H*hH*a-*XE z47W_<_cafQhe-k6u_~?4ZS}(T=%U>9brL|lPM&tmiEmcWxCaL1|Kh_@ojNw5bbiSW zA0?Y*r`cNrU35XHEv{8XG+4>~Ll2Kk&C5cM^N7oMNa|cyU*&udd0t{}DGA+QKZ299 zQqPl~f4taKPs#lEZqMlsaG4Oy?G}fV#VQ7H`i#yRPkSgCTbYXhE{D2Gu_2l)i@sMa z-6?QYaQfkUp_Fm|-b#*EASIx6-;xavm8#F$a!QMILmvlBkvz-%$V9O?(5s}Wm>2N+ zARjS!au=`jT_d@R!QvV_tJci*OsMnSDp~C93|{JI|GhN{9qi9r%}1uy%9E5K-$nh} z)WBEUJ(FFlHjs`+L!i^rXL{}E+nEwfSL*bTceUEGg-7$9NBa))@4IIT_^?H7|SopyAmg`kk=svLu~#QB3^JAroWa9JT&AUGx$J)1YSwu1Hnu609gJFV)`FV;CuX^$iYvaAv)FH z=^4S2vit4ZwO@9+py5=#$*7na{D)Il{k0T0^u~bCVZ95coRU*fEz}u_!lDpJffL%+om3vD68yo}5m0ClK!?Ac%3kz1;O)g6Lj36-a8|-@k zqaV9mUy+cHG2gt_*|fkgQ!vt@fb;9NLM#a_Z6p|Ph=z}^TXDaWc;1g>1WV@sk)VnAJ!gCU`~+SvSi!*7e|X)&1Adi;pNs>8ysBUr z#mZ(DdTXk4iTtXT2zK+Z(!E`O^2wQx#}TC1hZiQyfK#*r7!4)>(b6&p~& zxwgXEsA8icQ(YixOGPX7$bUHKhpVj#FiSWM>`DL9`~HB>ZnfAqJskrETP}2YfL4ff z-4iVC@YEi<9vx%@EGCbHbml-R=1)8$&2EEp(?k|Cw%+yZ0R>rKx4O6FK%l<@_JEi`i$05((%tAN^OW4ZuD5o(55Y~aWBSSRbF8<`$7k%hBz3z;%{zd zuwJHxoP##z%;!}~+#ZM4rc*MeLT@I5qaYP)PrCNU=<~fD2P9s&-40TJm*?3QYB~?s zKiUnA$GHIAMqWGiPn4iqTMpLj<)P9?)3;s`UBzupZ+QQeeeUU8$=LnZ=4i!^bLl-338Z<~9)$+HPF5lU%tR6 z{Z}J^f9Ao#WtNuGCf~QT6R?i!r{wVBP$MpZ_VVZ*;;x;aw6OXJl&qqA{prP^fBaVQ zJu8#RANjHPO`9RE`Plmjc<53v%~-k@Z0X&}3DsS2L2d6tXZbnx*ky4%IV(8*&C?tr z8&GodSOihU!0Er0TF~ZeEnq7-!sP9OsThNLnJkX<%$N0jVg?NtcO*BEoeqa7n+%uY zLEz%$ZD?}($X$M2R%(o-gnbUKDad9$aw+OvF9yLP(vQz6#Amd9v$XAiB1zF`J7!zH zwt@XdA?I?Q-xb!N#3nO`?yN{c^r#Co~bKnWo&1D{=17IHsE-V_@qfsLigSr_ zKj&%a>ncn37LTR~dJFq!OE?rXWX1$WQuM#y6E4L7U=aX|SE8uLsu%q6>4G8zH?L(- z>PW(tN8+6!BVs!WyXjQCQ_L-J>igYuJ!%}#$>~&Np&aDa=QRVjc+O&1Z;`z8q0FmG z(8UArowg>oj38`Xg(E)ASA5R%QMl%be6^&)hdz=ga>B!3hrL=Sv^29XTg#gttbeHq zr5;_;?Tf!|ZDiyluSxt;z?OJ$9g;E%^Qm>ajaVJ+Pt(Ny<8koc*x}*HfFZ=-NH6J+ zAAeyGzjr;X4v6YBjUftszhqBhSk9}uV_+S%E;>&#JZ-s~^VIlHM%yHmT`EkUtVrPg z$(e|NOv%k3o}@=hqppT^($$^}19(L}P$Q|z1QDJqN+uSn#bfzk*x0qFrD=f2jPA7l zH$E)lF;n}L+pINtqeXO4Jb|S5y11)r)$snC$O#()Uk9-BO2(;bG8sl0Ejb54+w(zz zK~M_JJwV5=l$^KtZ6hCi=$=4cr!IiLJ=A8ph*dqySSBKCO~(o^OT*JaJ3%373n-H( z1{T|ey9C3L7t8ztReA6i$Te;|KY8PAkcI5|QODtL2U^-x2t~w_JWSiZEIpGM9=e#y zJ}fFEdZ_El+udi!a&U0a>9wKx`T2qQnTD?lLx}@Qi}U;G#>gjoT=pDLD#xt!Oyxqw z$=@}~Fs?8(nMf?dqZNc~%#_ReG0m3J&M45aKkehj`K070VoQ!4t+s`ZhFuPi318P* z-KYc~Y7%zlFhAkjuyP;5NmN>3^(m_lXWI#**q@SxSsxPhw+R~Wkkh<(S-?zWAec(O z*@iV|9R2I*-j@_sDTV3jT266a`R{mVMWa+ob=1@0dj<_(k4gY4K=n7d^I*SJ zBv)(Rf$3~zFp~-aL&(xLym-OBCB$&5b_RblYJFmqp(20)$SI9uARe{n0Ip^*3C8XJ z=L-XWMm=n{MU)}!Z+>l0i`^QC{@h;^ze3Saw4^7lIJV;_z z#4-GXC5sj>4w$eYfJZE?$LklEq?adWcD7t6G(9fPVI_mQ(^-{;EhH8K?Z|PfIoOu| zaet+|it}A{>-?E;i$lW_OqbggdrU%#KFo9X(ec7{j zXO^7-i`aWd55aHobN;qDu)nm@D~?vUeHawQ8p${sfzG!6cWbs%KY^metp>hh{;XQqK+)JEGtkG`m88WMv3Dy&mKtGP zrikf@OMkMbG$#Ovp%(;lfW;_Zd_H{pSB{djBf%)||JvwP!DtRHwxN<{CS@VIO zDfqIhu|@Rw_&H!Z!WiYYr$0{`OFjmA=}01aL;{xaF4>Zi-1M|Js@49%C0XC6(6gR&Ofr$dl07>t^~aO9ZQ7c za-{h7mHv^D!1VL^w_}`iyJyrpm2I2`04s}>n;RTeG#iT}0Vm0U!QcadaHwhES~!T~ zn$;SKSy_4&O`zk-+zx!@rq+dUaM^={>+9IvPgb6q89T|x4ORG$9&T7h90w%y5sx#UB&E9#jwl-JL92DW?q?a1;;kAosKNV#Ry`K)I*{!PLQi80dR7Kg}j zw+{kr$1otXdt literal 28082 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 N{h}yY_1P%!e*mU$1A71f From a5ba57224b1e9cf63984c201916a4534d099e5ab Mon Sep 17 00:00:00 2001 From: ColinLug Date: Sat, 15 Mar 2025 10:23:30 +0100 Subject: [PATCH 12/86] =?UTF-8?q?Corrections=20de=20l'interface=20(URL=20n?= =?UTF-8?q?'=C3=A9tait=20pas=20une=20formulation=20claire)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/SciHubatorTest.py | 4 ++-- specs/images/scihubator_minimal.png | Bin 19292 -> 18936 bytes specs/images/scihubator_principal.png | Bin 30991 -> 31083 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index d75cdb07..c0ef5512 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -36,7 +36,7 @@ class SciHubator(widget.OWWidget): master=self, value='URL', orientation='horizontal', - label=u'DOI/URL:', + label=u'DOI:', labelWidth=101, callback=self.sendButton.settingsChanged, tooltip=( @@ -195,7 +195,7 @@ def __init__(self): master=self, value='newURL', orientation='horizontal', - label=u'URL(s):', + label=u'DOI(s):', labelWidth=101, callback=self.updateGUI, tooltip=( diff --git a/specs/images/scihubator_minimal.png b/specs/images/scihubator_minimal.png index 28286d7d92518e1e6fe8dafd11a270fcad63c058..ab8ceaf0011f520106df402638b7b6733dee6339 100644 GIT binary patch delta 15467 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 delta 15826 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 Z*|`2G@;D+|KzBBnq^O)og^+>&{{k4B;1~b^ diff --git a/specs/images/scihubator_principal.png b/specs/images/scihubator_principal.png index 49519632cc4fce23f5034633ba39cf2323734fac..819a38e75ec16e98f894ca22fbaa6e68e33dc28d 100644 GIT binary patch delta 27394 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Μ8PnSNg&bK$PB( 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 EA4`8j!vFvP delta 27296 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 F{|63Q{%ZgL From 96c6ad6a4ca853dd87ab7a14e03e5ce4c7811e7d Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:29:30 +0100 Subject: [PATCH 13/86] Update SCi-Hubator.rst Ajout du lien vers scihub.py --- specs/SCi-Hubator.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index 767aa900..3cbab26d 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -61,7 +61,7 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext =============== * Orange 3.38.1 * Orange Textable 3.2.2 -* scihub.py +* `scihub.py `_ * PyMuPDF 1.25.4 (déjà présent pour SuperTextFiles) @@ -113,4 +113,4 @@ TODO 4. Infrastructure ================= Le projet est disponible sur GitHub à l'adresse `https://github.com/sarahperettipoix/orange3-textable-prototypes' -_ +`_ From 025b856261f8852206a2670457856d4c7e9f331a Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:29:52 +0100 Subject: [PATCH 14/86] Update SCi-Hubator.rst --- specs/SCi-Hubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index 3cbab26d..9ff83841 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -112,5 +112,5 @@ TODO 4. Infrastructure ================= -Le projet est disponible sur GitHub à l'adresse `https://github.com/sarahperettipoix/orange3-textable-prototypes' +Le projet est disponible sur GitHub à l'adresse `https://github.com/sarahperettipoix/orange3-textable-prototypes `_ From 473897f9784d06740135fff2b7804e68899c0c20 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Mon, 24 Mar 2025 11:32:14 +0100 Subject: [PATCH 15/86] ajout DemoTextableWidget.py --- .../widgets/DemoTextableWidget.py | 340 ++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 orangecontrib/textable_prototypes/widgets/DemoTextableWidget.py diff --git a/orangecontrib/textable_prototypes/widgets/DemoTextableWidget.py b/orangecontrib/textable_prototypes/widgets/DemoTextableWidget.py new file mode 100644 index 00000000..30c058bc --- /dev/null +++ b/orangecontrib/textable_prototypes/widgets/DemoTextableWidget.py @@ -0,0 +1,340 @@ +""" +Class DemoTextableWidget +Copyright 2025 University of Lausanne +----------------------------------------------------------------------------- +This file is part of the Orange3-Textable-Prototypes package. + +Orange3-Textable-Prototypes is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +Orange3-Textable-Prototypes is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Orange3-Textable-Prototypes. If not, see + . +""" + +__version__ = '0.0.1' +__author__ = "Aris Xanthos" +__maintainer__ = "Aris Xanthos" +__email__ = "aris.xanthos@unil.ch" + + +from functools import partial +import time + +from _textable.widgets.TextableUtils import ( + OWTextableBaseWidget, VersionedSettingsHandler, ProgressBar, + InfoBox, SendButton, pluralize, Task +) + +from LTTL.Segmentation import Segmentation +from LTTL.Input import Input + +# Using the threaded version of LTTL.Segmenter to create +# a "responsive" widget. +import LTTL.SegmenterThread as Segmenter + +from Orange.widgets import widget, gui, settings +from Orange.widgets.utils.widgetpreview import WidgetPreview + + +class DemoTextableWidget(OWTextableBaseWidget): + """Demo Orange3-Textable widget""" + + name = "Demo widget" + description = "Illustrates common code behind Textable widgets" + icon = "icons/someIcon.svg" + priority = 99 + + # Input and output channels (remove if not needed)... + inputs = [("Segmentation", Segmentation, "inputData")] + outputs = [("New segmentation", Segmentation)] + + # Copied verbatim in every Textable widget to facilitate + # settings management. + settingsHandler = VersionedSettingsHandler( + version=__version__.rsplit(".", 1)[0] + ) + + # Settings... + segmentContent = settings.Setting("sample text") + numberOfSegments = settings.Setting("10") + + want_main_area = False + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Attributes... + self.inputSegmentationLength = 0 + + # The following attribute is required by every widget + # that imports new strings into Textable. + self.createdInputs = list() + + self.infoBox = InfoBox(widget=self.controlArea) + self.sendButton = SendButton( + widget=self.controlArea, + master=self, + callback=self.sendData, + cancelCallback=self.cancel_manually, + infoBoxAttribute="infoBox", + ) + + # GUI... + + # Top-level GUI boxes are created using method + # create_widgetbox(), so that they are automatically + # enabled/disabled when processes are running. + optionsBox = self.create_widgetbox( + box=u'Options', + orientation='vertical', + addSpace=False, + ) + + # GUI elements can be assigned to variables or even + # attributes (e.g. self.segmentContentLineEdit) if + # they must be referred to elsewhere, e.g., to enable + # or disable them, etc. It is not the case below. + gui.lineEdit( + widget=optionsBox, + master=self, + value="segmentContent", + orientation="horizontal", + label="Segment text:", + labelWidth=130, + # self.sendButton.settingsChanged should be used in + # in cases where using a GUI element should result + # in sending data to output. If it should result in + # other operations being done, use a custom method + # instead, and at the end of it, if data should be + # sent to output, call self.sendButton.settingsChanged(). + # If using the GUI element should not result in + # anything at that moment, delete the "callback" + # parameter. + callback=self.sendButton.settingsChanged, + tooltip=( + "A string that defines the content " + "each segment." + ), + ) + + gui.comboBox( + widget=optionsBox, + master=self, + value="numberOfSegments", + items=["1", "10", "100", "1000", "10000"], + sendSelectedValue=True, + orientation='horizontal', + label="Number of segments:", + labelWidth=130, + callback=self.sendButton.settingsChanged, + tooltip="Number of segments to create.", + ) + + # Stretchable vertical spacing between "options" + # and Send button etc. + gui.rubber(self.controlArea) + + # Draw send button & Info box... + self.sendButton.draw() + self.infoBox.draw() + + # Send data if needed. + self.sendButton.settingsChanged() + + def inputData(self, segmentation): + """Handle segmentation on input connection""" + + # If the input is None and it is needed for the widget + # to operate, send None to output(s) then return. + # Here, the widget can still operate without input. + if segmentation is None: + self.inputSegmentationLength = 0 + else: + self.inputSegmentationLength = len(segmentation) + + # Display the standard message for "input changed". + self.infoBox.inputChanged() + + def sendData(self): + """Perform every required check and operation + before calling the method that does the actual + processing. + """ + + if self.segmentContent == "": + # Use mode "warning" when user needs to do some + # action or provide some information; use mode "error" + # when invalid parameters have been provided; + # for notifications that don't require user action, + # don't use a mode. Use formulations that emphasize + # what should be done rather than what is wrong or + # missing. + self.infoBox.setText("Please type segment content.", + "warning") + # Make sure to send None and return if the widget + # cannot operate properly at this point. + self.send("New segmentation", None) + return + + # If the widget creates new LTTL.Input objects (i.e. + # if it imports new strings in Textable), make sure to + # clear previously created Inputs with this method. + self.clearCreatedInputs() + + # Notify processing in infobox. Typically, there should + # always be a "processing" step, with optional "pre- + # processing" and "post-processing" steps before and + # after it. If there are no optional steps, notify + # "Preprocessing...". + self.infoBox.setText("Step 1/2: Processing...", "warning") + + # Progress bar should be initialized at this point. + self.progressBarInit() + + # Create a threaded function to do the actual processing + # and specify its arguments (here there are none). + threaded_function = partial( + self.processData, + # argument1, + # argument2, + # ... + ) + + # Run the threaded function... + self.threading(threaded_function) + + def processData(self): + """Actual processing takes place in this method, + which is run in a worker thread so that GUI stays + responsive and operations can be cancelled + """ + + # At start of processing, set progress bar to 1%. + # Within this method, this is done using the following + # instruction. + self.signal_prog.emit(1, False) + + # Indicate the total number of iterations that the + # progress bar will go through (e.g. number of input + # segments, number of selected files, etc.), then + # set current iteration to 1. + max_itr = int(self.numberOfSegments) + cur_itr = 1 + + # Actual processing... + + # For each progress bar iteration... + for _ in range(int(self.numberOfSegments)): + + # Update progress bar manually... + self.signal_prog.emit(int(100*cur_itr/max_itr), False) + cur_itr += 1 + + # Create an LTTL.Input... + if int(self.numberOfSegments) == 1: + # self.captionTitle is the name of the widget, + # which will become the label of the output + # segmentation. + label = self.captionTitle + else: + label = None # will be set later. + myInput = Input(self.segmentContent, label) + + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. + segment = myInput[0] + segment.annotations["demo_annotation"] \ + = self.inputSegmentationLength + # For the annotation to be saved in the LTTL.Input, + # the extracted and annotated segment must be re-assigned + # to the first (and only) segment of the LTTL.Input. + myInput[0] = segment + + # Add the LTTL.Input to self.createdInputs. + self.createdInputs.append(myInput) + + # Cancel operation if requested by user... + time.sleep(0.00001) # Needed somehow! + if self.cancel_operation: + self.signal_prog.emit(100, False) + return + + # Update infobox and reset progress bar... + self.signal_text.emit("Step 2/2: Post-processing...", + "warning") + self.signal_prog.emit(1, True) + + # If there's only one LTTL.Input created, it is the + # widget's output... + if int(self.numberOfSegments) == 1: + return self.createdInputs[0] + + # Otherwise the widget's output is a concatenation... + else: + return Segmenter.concatenate( + caller=self, + segmentations=self.createdInputs, + label=self.captionTitle, + import_labels_as=None, + ) + + @OWTextableBaseWidget.task_decorator + def task_finished(self, f): + """All operations following the successful termination + of self.processData + """ + + # Get the result value of self.processData. + processed_data = f.result() + + # If it is not None... + if processed_data: + message = f"{len(processed_data)} segment@p sent to output " + message = pluralize(message, len(processed_data)) + numChars = 0 + for segment in processed_data: + segmentLength = len(Segmentation.get_data(segment.str_index)) + numChars += segmentLength + message += f"({numChars} character@p)." + message = pluralize(message, numChars) + self.infoBox.setText(message) + self.send("New segmentation", processed_data) + + # The following method should be copied verbatim in + # every Textable widget. + def setCaption(self, title): + """Register captionTitle changes and send if needed""" + if 'captionTitle' in dir(self): + changed = title != self.captionTitle + super().setCaption(title) + if changed: + self.cancel() # Cancel current operation + self.sendButton.settingsChanged() + else: + super().setCaption(title) + + # The following two methods should be copied verbatim in + # every Textable widget that creates LTTL.Input objects. + + def clearCreatedInputs(self): + """Clear created inputs""" + for i in self.createdInputs: + Segmentation.set_data(i[0].str_index, None) + del self.createdInputs[:] + + def onDeleteWidget(self): + """Clear created inputs on widget deletion""" + self.clearCreatedInputs() + + +if __name__ == '__main__': + WidgetPreview(DemoTextableWidget).run() From adba07011a086e085061814572ddeed16288e531 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Mon, 24 Mar 2025 15:42:05 +0100 Subject: [PATCH 16/86] Tentative de faire fonctionner les listes d'importations --- .../widgets/SciHubatorTest.py | 627 ++++++++++++------ 1 file changed, 412 insertions(+), 215 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index c0ef5512..980e1073 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -1,6 +1,35 @@ +""" +Class SuperTextFiles +Copyright 2020-2025 University of Lausanne +----------------------------------------------------------------------------- +This file is part of the Orange3-Textable-Prototypes package and based on the +file OWTextableTextFiles of the Orange3-Textable package. + +Orange3-Textable-Prototypes is free software: you can redistribute it +and/or modify it under the terms of the GNU General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Orange3-Textable-Prototypes is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Orange-Textable-Prototypes. If not, see +. +""" + +__version__ = u"0.0.1" +__author__ = "Sarah Perreti-Poix, Borgeaud Matthias, Chétioui Orsowen, Luginbühl Colin" +__maintainer__ = "Aris Xanthos" +__email__ = "aris.xanthos@unil.ch" + # Standard imports... import re import http +# from scihub import SciHub +import pdfplumber from Orange.widgets import widget, gui, settings from Orange.widgets.utils.widgetpreview import WidgetPreview from Orange.widgets.settings import Setting @@ -12,10 +41,9 @@ ) from LTTL.Segmentation import Segmentation -__version__ = "0.01" -class SciHubator(widget.OWWidget): +class SciHubator(OWTextableBaseWidget): """An Orange widget that lets the user select an integer value""" #Version minimale @@ -43,6 +71,7 @@ class SciHubator(widget.OWWidget): u"The URL whose content will be imported." ), ) + gui.rubber(self.controlArea) self.exportButton = gui.button( widget=URLBoxCol2, @@ -61,7 +90,7 @@ class SciHubator(widget.OWWidget): callback=self.importList, tooltip=( u"Open a dialog for selecting an URL list to\n" - u"import (in JSON format). URLs from this list will\n" + u"import (in JSON format). DOIs from this list will\n" u"be added to those already imported." ), ) @@ -90,16 +119,15 @@ class SciHubator(widget.OWWidget): # ---------------------------------------------------------------------- # Settings declaration and initializations (default values)... - URLs = Setting([]) + DOIs = Setting([]) encoding = Setting('(auto-detect)') autoNumber = Setting(False) autoNumberKey = Setting(u'num') autoSend = settings.Setting(False) - importURLs = Setting(True) - importURLsKey = Setting(u'url') + importDOIs = Setting(True) + importDOIsKey = Setting(u'url') lastLocation = Setting('.') - URL = Setting(u'') - selected_int = Setting(50) + DOI = Setting(u'') # Ici-dessous les variables qui n'ont pas été copiées, et conçues spécialement pour SciHubator importAll = Setting(True) @@ -111,17 +139,19 @@ def __init__(self): super().__init__() self.URLLabel = list() self.selectedURLLabel = list() - self.newURL = u'' - self.newAnnotationKey = u'' - self.newAnnotationValue = u'' + self.newDOI = u'' + self.extractedText = u'' + self.DOI = u'' + self.DOIs = list() + self.createdInputs = list() self.infoBox = InfoBox(widget=self.controlArea) self.sendButton = SendButton( widget=self.controlArea, master=self, - callback=self.int_changed, - infoBoxAttribute='infoBox', - sendIfPreCallback=self.int_changed, + callback=self.sendData, + cancelCallback=self.cancel_manually, + infoBoxAttribute="infoBox", ) # ---------------------------------------------------------------------- # User interface... @@ -148,7 +178,7 @@ def __init__(self): labels='URLLabel', callback=self.updateURLBoxButtons, tooltip=( - u"The list of URLs whose content will be imported.\n" + u"The list of DOIs whose content will be imported.\n" u"\nIn the output segmentation, the content of each\n" u"URL appears in the same position as in the list.\n" u"\nColumn 1 shows the URL.\n" @@ -175,7 +205,7 @@ def __init__(self): label=u'Clear All', callback=self.clearAll, tooltip=( - u"Remove all URLs from the list." + u"Remove all DOIs from the list." ), ) URLBoxLine2 = gui.widgetBox( @@ -193,15 +223,15 @@ def __init__(self): gui.lineEdit( widget=addURLBox, master=self, - value='newURL', + value='newDOI', orientation='horizontal', label=u'DOI(s):', labelWidth=101, callback=self.updateGUI, tooltip=( - u"The URL(s) that will be added to the list when\n" + u"The DOI(s) that will be added to the list when\n" u"button 'Add' is clicked.\n\n" - u"Successive URLs must be separated with ' / ' \n" + u"Successive DOIs must be separated with ' / ' \n" u"(space + slash + space). Their order in the list\n" u" will be the same as in this field." ), @@ -220,7 +250,7 @@ def __init__(self): labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( - u"Import URLs as annotations." + u"Import DOIs as annotations." ), ) gui.separator(widget=advOptionsBox, height=3) @@ -232,7 +262,7 @@ def __init__(self): labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( - u"Import URLs as annotations." + u"Import DOIs as annotations." ), ) gui.separator(widget=advOptionsBox, height=3) @@ -244,7 +274,7 @@ def __init__(self): labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( - u"Import URLs as annotations." + u"Import DOIs as annotations." ), ) gui.separator(widget=advOptionsBox, height=3) @@ -256,7 +286,7 @@ def __init__(self): labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( - u"Import URLs as annotations." + u"Import DOIs as annotations." ), ) gui.separator(widget=addURLBox, height=3) @@ -270,233 +300,400 @@ def __init__(self): u"text field to the list." ), ) + gui.rubber(self.controlArea) self.sendButton.draw() self.infoBox.draw() self.sendButton.sendIf() + + def sendData(self): + """Perform every required check and operation + before calling the method that does the actual + processing. + """ - def int_changed(self): - """Send the entered number on "Number" output""" - self.send("Text data", None) - - def importList(self): - """Display a FileDialog and import URL list""" - filePath, _ = QFileDialog.getOpenFileName( - self, - u'Import URL List', - self.lastLocation, - u'Text files (*)' - ) - if not filePath: + if self.DOI == "": + # Use mode "warning" when user needs to do some + # action or provide some information; use mode "error" + # when invalid parameters have been provided; + # for notifications that don't require user action, + # don't use a mode. Use formulations that emphasize + # what should be done rather than what is wrong or + # missing. + self.infoBox.setText("Please type DOI.", + "warning") + # Make sure to send None and return if the widget + # cannot operate properly at this point. + self.send("New segmentation", None) return - self.file = os.path.normpath(filePath) - self.lastLocation = os.path.dirname(filePath) - self.error() - try: - fileHandle = codecs.open(filePath, encoding='utf8') - fileContent = fileHandle.read() - fileHandle.close() - except IOError: - QMessageBox.warning( - None, - 'Textable', - "Couldn't open file.", - QMessageBox.Ok - ) - return - try: - json_data = json.loads(fileContent) - temp_URLs = list() - for entry in json_data: - URL = entry.get('url', '') - encoding = entry.get('encoding', '') - annotationKey = entry.get('annotation_key', '') - annotationValue = entry.get('annotation_value', '') - if URL == '' or encoding == '': - QMessageBox.warning( - None, - 'Textable', - "Selected JSON file doesn't have the right keys " - "and/or values.", - QMessageBox.Ok - ) - return - temp_URLs.append(( - URL, - encoding, - annotationKey, - annotationValue, - )) - self.URLs.extend(temp_URLs) - if temp_URLs: - self.sendButton.settingsChanged() - except ValueError: - QMessageBox.warning( - None, - 'Textable', - "Selected file is not in JSON format.", - QMessageBox.Ok - ) - return + # If the widget creates new LTTL.Input objects (i.e. + # if it imports new strings in Textable), make sure to + # clear previously created Inputs with this method. + self.clearCreatedInputs() - def exportList(self): - """Display a FileDialog and export URL list""" - toDump = list() - for URL in self.URLs: - toDump.append({ - 'url': URL[0], - 'encoding': URL[1], - }) - if URL[2] and URL[3]: - toDump[-1]['annotation_key'] = URL[2] - toDump[-1]['annotation_value'] = URL[3] - filePath, _ = QFileDialog.getSaveFileName( - self, - u'Export URL List', - self.lastLocation, + # Notify processing in infobox. Typically, there should + # always be a "processing" step, with optional "pre- + # processing" and "post-processing" steps before and + # after it. If there are no optional steps, notify + # "Preprocessing...". + self.infoBox.setText("Step 1/2: Processing...", "warning") + + # Progress bar should be initialized at this point. + self.progressBarInit() + + # Create a threaded function to do the actual processing + # and specify its arguments (here there are none). + threaded_function = partial( + self.processData, + # argument1, + # argument2, + # ... ) - if filePath: - self.lastLocation = os.path.dirname(filePath) - outputFile = codecs.open( - filePath, - encoding='utf8', - mode='w', - errors='xmlcharrefreplace', - ) - outputFile.write( - normalizeCarriageReturns( - json.dumps(toDump, sort_keys=True, indent=4) - ) - ) - outputFile.close() - QMessageBox.information( - None, - 'Textable', - 'URL list correctly exported', - QMessageBox.Ok - ) - def moveUp(self): - """Move URL upward in URLs listbox""" - if self.selectedURLLabel: - index = self.selectedURLLabel[0] - if index > 0: - temp = self.URLs[index-1] - self.URLs[index-1] = self.URLs[index] - self.URLs[index] = temp - self.selectedURLLabel = [index-1] - self.sendButton.settingsChanged() + # Run the threaded function... + self.threading(threaded_function) - def moveDown(self): - """Move URL downward in URLs listbox""" - if self.selectedURLLabel: - index = self.selectedURLLabel[0] - if index < len(self.URLs) - 1: - temp = self.URLs[index+1] - self.URLs[index+1] = self.URLs[index] - self.URLs[index] = temp - self.selectedURLLabel = [index+1] + def processData(self): + """Actual processing takes place in this method, + which is run in a worker thread so that GUI stays + responsive and operations can be cancelled + """ + + # At start of processing, set progress bar to 1%. + # Within this method, this is done using the following + # instruction. + self.signal_prog.emit(1, False) + + # Indicate the total number of iterations that the + # progress bar will go through (e.g. number of input + # segments, number of selected files, etc.), then + # set current iteration to 1. + max_itr = int(self.numberOfSegments) + cur_itr = 1 + + # Actual processing... + + # For each progress bar iteration... + for _ in range(int(self.numberOfSegments)): + + # Update progress bar manually... + self.signal_prog.emit(int(100*cur_itr/max_itr), False) + cur_itr += 1 + + # Create an LTTL.Input... + if int(self.numberOfSegments) == 1: + # self.captionTitle is the name of the widget, + # which will become the label of the output + # segmentation. + label = self.captionTitle + else: + label = None # will be set later. + myInput = Input(self.segmentContent, label) + + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. + segment = myInput[0] + segment.annotations["demo_annotation"] \ + = self.inputSegmentationLength + # For the annotation to be saved in the LTTL.Input, + # the extracted and annotated segment must be re-assigned + # to the first (and only) segment of the LTTL.Input. + myInput[0] = segment + + # Add the LTTL.Input to self.createdInputs. + self.createdInputs.append(myInput) + + # Cancel operation if requested by user... + time.sleep(0.00001) # Needed somehow! + if self.cancel_operation: + self.signal_prog.emit(100, False) + return + + # Update infobox and reset progress bar... + self.signal_text.emit("Step 2/2: Post-processing...", + "warning") + self.signal_prog.emit(1, True) + + # If there's only one LTTL.Input created, it is the + # widget's output... + if int(self.numberOfSegments) == 1: + return self.createdInputs[0] + + # Otherwise the widget's output is a concatenation... + else: + return Segmenter.concatenate( + caller=self, + segmentations=self.createdInputs, + label=self.captionTitle, + import_labels_as=None, + ) + + @OWTextableBaseWidget.task_decorator + def task_finished(self, f): + """All operations following the successful termination + of self.processData + """ + + # Get the result value of self.processData. + processed_data = f.result() + + # If it is not None... + if processed_data: + message = f"{len(processed_data)} segment@p sent to output " + message = pluralize(message, len(processed_data)) + numChars = 0 + for segment in processed_data: + segmentLength = len(Segmentation.get_data(segment.str_index)) + numChars += segmentLength + message += f"({numChars} character@p)." + message = pluralize(message, numChars) + self.infoBox.setText(message) + self.send("New segmentation", processed_data) + + # The following method should be copied verbatim in + # every Textable widget. + def setCaption(self, title): + """Register captionTitle changes and send if needed""" + if 'captionTitle' in dir(self): + changed = title != self.captionTitle + super().setCaption(title) + if changed: + self.cancel() # Cancel current operation self.sendButton.settingsChanged() + else: + super().setCaption(title) def clearAll(self): - """Remove all URLs from URLs attr""" - del self.URLs[:] + """Remove all DOIs from DOIs attr""" + del self.DOIs[:] del self.selectedURLLabel[:] self.sendButton.settingsChanged() def remove(self): - """Remove URL from URLs attr""" + """Remove URL from DOIs attr""" if self.selectedURLLabel: index = self.selectedURLLabel[0] - self.URLs.pop(index) + self.DOIs.pop(index) del self.selectedURLLabel[:] self.sendButton.settingsChanged() def add(self): - """Add URLs to URLs attr""" - URLList = re.split(r' +/ +', self.newURL) - for URL in URLList: - encoding = re.sub(r"[ ]\(.+", "", self.encoding) - self.URLs.append(( - URL, - encoding, - self.newAnnotationKey, - self.newAnnotationValue, - )) + """Add DOIs to DOIs attr""" + DOIList = re.split(r'/', self.newDOI) + print(DOIList) + for DOI in DOIList: + print(DOI) + self.DOIs.append(DOI) self.sendButton.settingsChanged() + def updateGUI(self): """Update GUI state""" - if self.displayAdvancedSettings: - if self.selectedURLLabel: - cachedLabel = self.selectedURLLabel[0] - else: - cachedLabel = None - del self.URLLabel[:] - if self.URLs: - URLs = [f[0] for f in self.URLs] - encodings = [f[1] for f in self.URLs] - annotations = ['{%s: %s}' % (f[2], f[3]) for f in self.URLs] - maxURLLen = max([len(n) for n in URLs]) - maxAnnoLen = max([len(a) for a in annotations]) - for index in range(len(self.URLs)): - format = u'%-' + str(maxURLLen + 2) + u's' - URLLabel = format % URLs[index] - if maxAnnoLen > 4: - if len(annotations[index]) > 4: - format = u'%-' + str(maxAnnoLen + 2) + u's' - URLLabel += format % annotations[index] - else: - URLLabel += u' ' * (maxAnnoLen + 2) - URLLabel += encodings[index] - self.URLLabel.append(URLLabel) - self.URLLabel = self.URLLabel - if cachedLabel is not None: - self.sendButton.sendIfPreCallback = None - self.selectedURLLabel = [cachedLabel] - self.sendButton.sendIfPreCallback = self.updateGUI - if self.newURL: - if ( - (self.newAnnotationKey and self.newAnnotationValue) or - (not self.newAnnotationKey and not self.newAnnotationValue) - ): - self.addButton.setDisabled(False) - else: - self.addButton.setDisabled(True) - else: - self.addButton.setDisabled(True) - if self.autoNumber: - self.autoNumberKeyLineEdit.setDisabled(False) - else: - self.autoNumberKeyLineEdit.setDisabled(True) - if self.importURLs: - self.importURLsKeyLineEdit.setDisabled(False) - else: - self.importURLsKeyLineEdit.setDisabled(True) - self.updateURLBoxButtons() - self.advancedSettings.setVisible(True) + # if self.selectedURLLabel: + # cachedLabel = self.selectedURLLabel[0] + # else: + # cachedLabel = None + del self.URLLabel[:] + if self.DOIs: + DOIs = [f for f in self.DOIs] + # maxURLLen = max([len(n) for n in DOIs]) + for DOI in DOIs: #range(len(self.DOIs)): + # format = u'%-' + str(maxURLLen + 2) + u's' + #format % DOIs[index] + self.URLLabel.append(DOI) + self.URLLabel = self.URLLabel + # if cachedLabel is not None: + # self.sendButton.sendIfPreCallback = None + # self.selectedURLLabel = [cachedLabel] + # self.sendButton.sendIfPreCallback = self.updateGUI + if self.newDOI: + self.addButton.setDisabled(False) else: - self.advancedSettings.setVisible(False) + self.addButton.setDisabled(True) + # if self.importDOIs: + # self.importDOIsKeyLineEdit.setDisabled(False) + # else: + # self.importDOIsKeyLineEdit.setDisabled(True) + self.updateURLBoxButtons() + # if self.displayAdvancedSettings: + # if self.selectedURLLabel: + # cachedLabel = self.selectedURLLabel[0] + # else: + # cachedLabel = None + # del self.URLLabel[:] + # if self.DOIs: + # DOIs = [f[0] for f in self.DOIs] + # encodings = [f[1] for f in self.DOIs] + # annotations = ['{%s: %s}' % (f[2], f[3]) for f in self.DOIs] + # maxURLLen = max([len(n) for n in DOIs]) + # maxAnnoLen = max([len(a) for a in annotations]) + # for index in range(len(self.DOIs)): + # format = u'%-' + str(maxURLLen + 2) + u's' + # URLLabel = format % DOIs[index] + # if maxAnnoLen > 4: + # if len(annotations[index]) > 4: + # format = u'%-' + str(maxAnnoLen + 2) + u's' + # URLLabel += format % annotations[index] + # else: + # URLLabel += u' ' * (maxAnnoLen + 2) + # URLLabel += encodings[index] + # self.URLLabel.append(URLLabel) + # self.URLLabel = self.URLLabel + # if cachedLabel is not None: + # self.sendButton.sendIfPreCallback = None + # self.selectedURLLabel = [cachedLabel] + # self.sendButton.sendIfPreCallback = self.updateGUI + # if self.newURL: + # if ( + # (self.newAnnotationKey and self.newAnnotationValue) or + # (not self.newAnnotationKey and not self.newAnnotationValue) + # ): + # self.addButton.setDisabled(False) + # else: + # self.addButton.setDisabled(True) + # else: + # self.addButton.setDisabled(True) + # if self.autoNumber: + # self.autoNumberKeyLineEdit.setDisabled(False) + # else: + # self.autoNumberKeyLineEdit.setDisabled(True) + # if self.importDOIs: + # self.importDOIsKeyLineEdit.setDisabled(False) + # else: + # self.importDOIsKeyLineEdit.setDisabled(True) + # self.updateURLBoxButtons() + # self.advancedSettings.setVisible(True) + # else: + # self.advancedSettings.setVisible(False) def updateURLBoxButtons(self): """Update state of File box buttons""" if self.selectedURLLabel: self.removeButton.setDisabled(False) - if self.selectedURLLabel[0] > 0: - self.moveUpButton.setDisabled(False) - else: - self.moveUpButton.setDisabled(True) - if self.selectedURLLabel[0] < len(self.URLs) - 1: - self.moveDownButton.setDisabled(False) - else: - self.moveDownButton.setDisabled(True) else: - self.moveUpButton.setDisabled(True) - self.moveDownButton.setDisabled(True) self.removeButton.setDisabled(True) - if len(self.URLs): + if len(self.DOIs): self.clearAllButton.setDisabled(False) - self.exportButton.setDisabled(False) else: self.clearAllButton.setDisabled(True) - self.exportButton.setDisabled(True) + + + # The following two methods should be copied verbatim in + # every Textable widget that creates LTTL.Input objects. + + def clearCreatedInputs(self): + """Clear created inputs""" + for i in self.createdInputs: + Segmentation.set_data(i[0].str_index, None) + del self.createdInputs[:] + + def onDeleteWidget(self): + """Clear created inputs on widget deletion""" + self.clearCreatedInputs() + +if __name__ == '__main__': + WidgetPreview(SciHubator).run() + + + # def clearAll(self): + # """Remove all DOIs from DOIs attr""" + # del self.DOIs[:] + # del self.selectedURLLabel[:] + # self.sendButton.settingsChanged() + + # def remove(self): + # """Remove URL from DOIs attr""" + # if self.selectedURLLabel: + # index = self.selectedURLLabel[0] + # self.DOIs.pop(index) + # del self.selectedURLLabel[:] + # self.sendButton.settingsChanged() + + # def add(self): + # """Add DOIs to DOIs attr""" + # URLList = re.split(r' +/ +', self.newURL) + # for URL in URLList: + # encoding = re.sub(r"[ ]\(.+", "", self.encoding) + # self.DOIs.append(( + # URL, + # encoding, + # self.newAnnotationKey, + # self.newAnnotationValue, + # )) + # self.sendButton.settingsChanged() + # def updateGUI(self): + # """Update GUI state""" + # if self.displayAdvancedSettings: + # if self.selectedURLLabel: + # cachedLabel = self.selectedURLLabel[0] + # else: + # cachedLabel = None + # del self.URLLabel[:] + # if self.DOIs: + # DOIs = [f[0] for f in self.DOIs] + # encodings = [f[1] for f in self.DOIs] + # annotations = ['{%s: %s}' % (f[2], f[3]) for f in self.DOIs] + # maxURLLen = max([len(n) for n in DOIs]) + # maxAnnoLen = max([len(a) for a in annotations]) + # for index in range(len(self.DOIs)): + # format = u'%-' + str(maxURLLen + 2) + u's' + # URLLabel = format % DOIs[index] + # if maxAnnoLen > 4: + # if len(annotations[index]) > 4: + # format = u'%-' + str(maxAnnoLen + 2) + u's' + # URLLabel += format % annotations[index] + # else: + # URLLabel += u' ' * (maxAnnoLen + 2) + # URLLabel += encodings[index] + # self.URLLabel.append(URLLabel) + # self.URLLabel = self.URLLabel + # if cachedLabel is not None: + # self.sendButton.sendIfPreCallback = None + # self.selectedURLLabel = [cachedLabel] + # self.sendButton.sendIfPreCallback = self.updateGUI + # if self.newURL: + # if ( + # (self.newAnnotationKey and self.newAnnotationValue) or + # (not self.newAnnotationKey and not self.newAnnotationValue) + # ): + # self.addButton.setDisabled(False) + # else: + # self.addButton.setDisabled(True) + # else: + # self.addButton.setDisabled(True) + # if self.autoNumber: + # self.autoNumberKeyLineEdit.setDisabled(False) + # else: + # self.autoNumberKeyLineEdit.setDisabled(True) + # if self.importDOIs: + # self.importDOIsKeyLineEdit.setDisabled(False) + # else: + # self.importDOIsKeyLineEdit.setDisabled(True) + # self.updateURLBoxButtons() + # self.advancedSettings.setVisible(True) + # else: + # self.advancedSettings.setVisible(False) + + # def updateURLBoxButtons(self): + # """Update state of File box buttons""" + # if self.selectedURLLabel: + # self.removeButton.setDisabled(False) + # if self.selectedURLLabel[0] > 0: + # self.moveUpButton.setDisabled(False) + # else: + # self.moveUpButton.setDisabled(True) + # if self.selectedURLLabel[0] < len(self.DOIs) - 1: + # self.moveDownButton.setDisabled(False) + # else: + # self.moveDownButton.setDisabled(True) + # else: + # self.moveUpButton.setDisabled(True) + # self.moveDownButton.setDisabled(True) + # self.removeButton.setDisabled(True) + # if len(self.DOIs): + # self.clearAllButton.setDisabled(False) + # self.exportButton.setDisabled(False) + # else: + # self.clearAllButton.setDisabled(True) + # self.exportButton.setDisabled(True) From 9c394bd68ded082e3a6035f0fc0563bbc00f1254 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Mon, 24 Mar 2025 16:26:46 +0100 Subject: [PATCH 17/86] Boutons add, remove et clearall fonctionnent par la magie du Monstre en spaghetti volant --- .../widgets/SciHubatorTest.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 980e1073..f5af9fff 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -198,6 +198,7 @@ def __init__(self): tooltip=( u"Remove the selected URL from the list." ), + disabled = True, ) self.clearAllButton = gui.button( widget=URLBoxCol2, @@ -207,6 +208,7 @@ def __init__(self): tooltip=( u"Remove all DOIs from the list." ), + disabled = True, ) URLBoxLine2 = gui.widgetBox( widget=URLBox, @@ -299,6 +301,7 @@ def __init__(self): u"Add the URL currently displayed in the 'URL'\n" u"text field to the list." ), + disabled = True, ) gui.rubber(self.controlArea) self.sendButton.draw() @@ -469,6 +472,9 @@ def clearAll(self): del self.DOIs[:] del self.selectedURLLabel[:] self.sendButton.settingsChanged() + # Ne devrait pas être nécessaire non ? + # Rajoutée anyway + self.updateGUI() def remove(self): """Remove URL from DOIs attr""" @@ -477,6 +483,9 @@ def remove(self): self.DOIs.pop(index) del self.selectedURLLabel[:] self.sendButton.settingsChanged() + # Ne devrait pas être nécessaire non ? + # Rajoutée anyway + self.updateGUI() def add(self): """Add DOIs to DOIs attr""" @@ -486,6 +495,9 @@ def add(self): print(DOI) self.DOIs.append(DOI) self.sendButton.settingsChanged() + # Ne devrait pas être nécessaire non ? + # Rajoutée anyway + self.updateGUI() def updateGUI(self): """Update GUI state""" @@ -496,11 +508,12 @@ def updateGUI(self): del self.URLLabel[:] if self.DOIs: DOIs = [f for f in self.DOIs] + self.URLLabel = DOIs # maxURLLen = max([len(n) for n in DOIs]) - for DOI in DOIs: #range(len(self.DOIs)): + # for DOI in DOIs: #range(len(self.DOIs)): # format = u'%-' + str(maxURLLen + 2) + u's' #format % DOIs[index] - self.URLLabel.append(DOI) + # self.URLLabel.append(DOI) self.URLLabel = self.URLLabel # if cachedLabel is not None: # self.sendButton.sendIfPreCallback = None @@ -697,3 +710,5 @@ def onDeleteWidget(self): # self.clearAllButton.setDisabled(True) # self.exportButton.setDisabled(True) +# def checkIfDOI(string): +# regex = re.compile(r'\d{2}\.\d{4}.+') \ No newline at end of file From a0b159edd009500fb844df54e027823d3b9b5d21 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Mon, 24 Mar 2025 16:32:03 +0100 Subject: [PATCH 18/86] Boutons add, remove et clearall fonctionnent par la magie du Monstre en spaghetti volant --- .../widgets/SciHubatorTest.py | 50 ------------------- 1 file changed, 50 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index f5af9fff..9ed9b31d 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -528,56 +528,6 @@ def updateGUI(self): # else: # self.importDOIsKeyLineEdit.setDisabled(True) self.updateURLBoxButtons() - # if self.displayAdvancedSettings: - # if self.selectedURLLabel: - # cachedLabel = self.selectedURLLabel[0] - # else: - # cachedLabel = None - # del self.URLLabel[:] - # if self.DOIs: - # DOIs = [f[0] for f in self.DOIs] - # encodings = [f[1] for f in self.DOIs] - # annotations = ['{%s: %s}' % (f[2], f[3]) for f in self.DOIs] - # maxURLLen = max([len(n) for n in DOIs]) - # maxAnnoLen = max([len(a) for a in annotations]) - # for index in range(len(self.DOIs)): - # format = u'%-' + str(maxURLLen + 2) + u's' - # URLLabel = format % DOIs[index] - # if maxAnnoLen > 4: - # if len(annotations[index]) > 4: - # format = u'%-' + str(maxAnnoLen + 2) + u's' - # URLLabel += format % annotations[index] - # else: - # URLLabel += u' ' * (maxAnnoLen + 2) - # URLLabel += encodings[index] - # self.URLLabel.append(URLLabel) - # self.URLLabel = self.URLLabel - # if cachedLabel is not None: - # self.sendButton.sendIfPreCallback = None - # self.selectedURLLabel = [cachedLabel] - # self.sendButton.sendIfPreCallback = self.updateGUI - # if self.newURL: - # if ( - # (self.newAnnotationKey and self.newAnnotationValue) or - # (not self.newAnnotationKey and not self.newAnnotationValue) - # ): - # self.addButton.setDisabled(False) - # else: - # self.addButton.setDisabled(True) - # else: - # self.addButton.setDisabled(True) - # if self.autoNumber: - # self.autoNumberKeyLineEdit.setDisabled(False) - # else: - # self.autoNumberKeyLineEdit.setDisabled(True) - # if self.importDOIs: - # self.importDOIsKeyLineEdit.setDisabled(False) - # else: - # self.importDOIsKeyLineEdit.setDisabled(True) - # self.updateURLBoxButtons() - # self.advancedSettings.setVisible(True) - # else: - # self.advancedSettings.setVisible(False) def updateURLBoxButtons(self): """Update state of File box buttons""" From e6e9737b5dbb9f22b2379533cd073ef165f1fdc5 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 27 Mar 2025 11:18:05 +0100 Subject: [PATCH 19/86] version GUI minimale DEMO --- .../textable_prototypes/widgets/DemoSciHub.py | 340 ++++++++++++++++++ .../widgets/SciHubatorTest.py | 2 +- 2 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 orangecontrib/textable_prototypes/widgets/DemoSciHub.py diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py new file mode 100644 index 00000000..0d85c129 --- /dev/null +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -0,0 +1,340 @@ +""" +Class DemoTextableWidget +Copyright 2025 University of Lausanne +----------------------------------------------------------------------------- +This file is part of the Orange3-Textable-Prototypes package. + +Orange3-Textable-Prototypes is free software: you can redistribute +it and/or modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +Orange3-Textable-Prototypes is distributed in the hope that it will +be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Orange3-Textable-Prototypes. If not, see + . +""" + +__version__ = u"0.0.1" +__author__ = "Sarah Perreti-Poix, Borgeaud Matthias, Chétioui Orsowen, Luginbühl Colin" +__maintainer__ = "Aris Xanthos" +__email__ = "aris.xanthos@unil.ch" + + +from functools import partial +import time + +from _textable.widgets.TextableUtils import ( + OWTextableBaseWidget, VersionedSettingsHandler, ProgressBar, + InfoBox, SendButton, pluralize, Task +) + +from LTTL.Segmentation import Segmentation +#from LTTL.Input import Input + +# Using the threaded version of LTTL.Segmenter to create +# a "responsive" widget. +import LTTL.SegmenterThread as Segmenter + +from Orange.widgets import widget, gui, settings +from Orange.widgets.utils.widgetpreview import WidgetPreview + + +class DemoTextableWidget(OWTextableBaseWidget): + """Demo Orange3-Textable widget""" + + name = "Demo Scihub" + description = "Export a text segmentation from a DOI or URL" + icon = "icons/someIcon.svg" + priority = 99 + + # Input and output channels (remove if not needed)... + #inputs = [("Segmentation", Segmentation, "inputData")] + outputs = [("New segmentation", Segmentation)] + + # Copied verbatim in every Textable widget to facilitate + # settings management. + settingsHandler = VersionedSettingsHandler( + version=__version__.rsplit(".", 1)[0] + ) + + # Settings... + DOIContent = settings.Setting("") + #numberOfSegments = settings.Setting("10") + + want_main_area = False + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # The following attribute is required by every widget + # that imports new strings into Textable. + self.createdInputs = list() + + self.infoBox = InfoBox(widget=self.controlArea) + self.sendButton = SendButton( + widget=self.controlArea, + master=self, + callback=self.sendData, + cancelCallback=self.cancel_manually, + infoBoxAttribute="infoBox", + ) + + # GUI... + + # Top-level GUI boxes are created using method + # create_widgetbox(), so that they are automatically + # enabled/disabled when processes are running. + sourceBox = self.create_widgetbox( + box=u'Options', + orientation='vertical', + addSpace=False, + ) + + # GUI elements can be assigned to variables or even + # attributes (e.g. self.DOIContentLineEdit) if + # they must be referred to elsewhere, e.g., to enable + # or disable them, etc. It is not the case below. + gui.lineEdit( + widget=sourceBox, + master=self, + value="DOIContent", + orientation="horizontal", + label="DOI:", + labelWidth=130, + # self.sendButton.settingsChanged should be used in + # in cases where using a GUI element should result + # in sending data to output. If it should result in + # other operations being done, use a custom method + # instead, and at the end of it, if data should be + # sent to output, call self.sendButton.settingsChanged(). + # If using the GUI element should not result in + # anything at that moment, delete the "callback" + # parameter. + callback=self.sendButton.settingsChanged, + tooltip=( + "A string that defines the content " + "each segment." + ), + ) + +""" gui.comboBox( + widget=optionsBox, + master=self, + value="numberOfSegments", + items=["1", "10", "100", "1000", "10000"], + sendSelectedValue=True, + orientation='horizontal', + label="Number of segments:", + labelWidth=130, + callback=self.sendButton.settingsChanged, + tooltip="Number of segments to create.", + )""" + + # Stretchable vertical spacing between "options" + # and Send button etc. + gui.rubber(self.controlArea) + + # Draw send button & Info box... + self.sendButton.draw() + self.infoBox.draw() + + # Send data if needed. + self.sendButton.settingsChanged() + + """ def inputData(self, segmentation): + Handle segmentation on input connection + + # If the input is None and it is needed for the widget + # to operate, send None to output(s) then return. + # Here, the widget can still operate without input. + if segmentation is None: + self.inputSegmentationLength = 0 + else: + self.inputSegmentationLength = len(segmentation) + + # Display the standard message for "input changed". + self.infoBox.inputChanged()""" + + def sendData(self): + """Perform every required check and operation + before calling the method that does the actual + processing. + """ + + if self.DOIContent == "": + # Use mode "warning" when user needs to do some + # action or provide some information; use mode "error" + # when invalid parameters have been provided; + # for notifications that don't require user action, + # don't use a mode. Use formulations that emphasize + # what should be done rather than what is wrong or + # missing. + self.infoBox.setText("Please type valid DOI.", + "warning") + # Make sure to send None and return if the widget + # cannot operate properly at this point. + self.send("New DOI", None) + return + + # If the widget creates new LTTL.Input objects (i.e. + # if it imports new strings in Textable), make sure to + # clear previously created Inputs with this method. + self.clearCreatedInputs() + + # Notify processing in infobox. Typically, there should + # always be a "processing" step, with optional "pre- + # processing" and "post-processing" steps before and + # after it. If there are no optional steps, notify + # "Preprocessing...". + self.infoBox.setText("Step 1/2: Processing...", "warning") + + # Progress bar should be initialized at this point. + self.progressBarInit() + + # Create a threaded function to do the actual processing + # and specify its arguments (here there are none). + threaded_function = partial( + self.processData, + # argument1, + # argument2, + # ... + ) + + # Run the threaded function... + self.threading(threaded_function) + + def processData(self): + """Actual processing takes place in this method, + which is run in a worker thread so that GUI stays + responsive and operations can be cancelled + """ + + # At start of processing, set progress bar to 1%. + # Within this method, this is done using the following + # instruction. + self.signal_prog.emit(1, False) + + DOIList = [] + DOIList.append(self.DOIContent) + + # Indicate the total number of iterations that the + # progress bar will go through (e.g. number of input + # segments, number of selected files, etc.), then + # set current iteration to 1. + max_itr = len(DOIList) + cur_itr = 1 + + # Actual processing... + + # For each progress bar iteration... + for DOI in DOIList: + + # Update progress bar manually... + self.signal_prog.emit(int(100*cur_itr/max_itr), False) + cur_itr += 1 + + # Create an LTTL.Input... + if len(DOIList) == 1: + # self.captionTitle is the name of the widget, + # which will become the label of the output + # segmentation. + label = self.captionTitle + else: + label = None # will be set later. + myInput = Input(self.DOIContent, label) + + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. + segment = myInput[0] + segment.annotations["demo_annotation"] \ + = self.inputSegmentationLength + # For the annotation to be saved in the LTTL.Input, + # the extracted and annotated segment must be re-assigned + # to the first (and only) segment of the LTTL.Input. + myInput[0] = segment + + # Add the LTTL.Input to self.createdInputs. + self.createdInputs.append(myInput) + + # Cancel operation if requested by user... + time.sleep(0.00001) # Needed somehow! + if self.cancel_operation: + self.signal_prog.emit(100, False) + return + + # Update infobox and reset progress bar... + self.signal_text.emit("Step 2/2: Post-processing...", + "warning") + self.signal_prog.emit(1, True) + + # If there's only one LTTL.Input created, it is the + # widget's output... + if len(DOIList) == 1: + return self.createdInputs[0] + + # Otherwise the widget's output is a concatenation... + else: + return Segmenter.concatenate( + caller=self, + segmentations=self.createdInputs, + label=self.captionTitle, + import_labels_as=None, + ) + + @OWTextableBaseWidget.task_decorator + def task_finished(self, f): + """All operations following the successful termination + of self.processData + """ + + # Get the result value of self.processData. + processed_data = f.result() + + # If it is not None... + if processed_data: + message = "text sent to output " + message = pluralize(message, len(processed_data)) + """numChars = 0 + for segment in processed_data: + segmentLength = len(Segmentation.get_data(segment.str_index)) + numChars += segmentLength + message += f"({numChars} character@p)." + message = pluralize(message, numChars)""" + self.infoBox.setText(message) + self.send("New segmentation", processed_data) + + # The following method should be copied verbatim in + # every Textable widget. + def setCaption(self, title): + """Register captionTitle changes and send if needed""" + if 'captionTitle' in dir(self): + changed = title != self.captionTitle + super().setCaption(title) + if changed: + self.cancel() # Cancel current operation + self.sendButton.settingsChanged() + else: + super().setCaption(title) + + # The following two methods should be copied verbatim in + # every Textable widget that creates LTTL.Input objects. + + def clearCreatedInputs(self): + """Clear created inputs""" + for i in self.createdInputs: + Segmentation.set_data(i[0].str_index, None) + del self.createdInputs[:] + + def onDeleteWidget(self): + """Clear created inputs on widget deletion""" + self.clearCreatedInputs() + + +if __name__ == '__main__': + WidgetPreview(DemoTextableWidget).run() diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 9ed9b31d..b77a592c 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -28,7 +28,7 @@ # Standard imports... import re import http -# from scihub import SciHub +from scihub import SciHub import pdfplumber from Orange.widgets import widget, gui, settings from Orange.widgets.utils.widgetpreview import WidgetPreview From 22e5467beb4a7eb1dd0fc8537da059a41ec2b2ca Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 27 Mar 2025 11:48:07 +0100 Subject: [PATCH 20/86] version GUI minimale DEMO --- .../textable_prototypes/widgets/DemoSciHub.py | 32 ++----------------- .../widgets/SciHubatorTest.py | 3 +- 2 files changed, 4 insertions(+), 31 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index 0d85c129..79378ff7 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -85,7 +85,6 @@ def __init__(self, *args, **kwargs): ) # GUI... - # Top-level GUI boxes are created using method # create_widgetbox(), so that they are automatically # enabled/disabled when processes are running. @@ -93,7 +92,7 @@ def __init__(self, *args, **kwargs): box=u'Options', orientation='vertical', addSpace=False, - ) + ) # GUI elements can be assigned to variables or even # attributes (e.g. self.DOIContentLineEdit) if @@ -122,19 +121,6 @@ def __init__(self, *args, **kwargs): ), ) -""" gui.comboBox( - widget=optionsBox, - master=self, - value="numberOfSegments", - items=["1", "10", "100", "1000", "10000"], - sendSelectedValue=True, - orientation='horizontal', - label="Number of segments:", - labelWidth=130, - callback=self.sendButton.settingsChanged, - tooltip="Number of segments to create.", - )""" - # Stretchable vertical spacing between "options" # and Send button etc. gui.rubber(self.controlArea) @@ -146,20 +132,6 @@ def __init__(self, *args, **kwargs): # Send data if needed. self.sendButton.settingsChanged() - """ def inputData(self, segmentation): - Handle segmentation on input connection - - # If the input is None and it is needed for the widget - # to operate, send None to output(s) then return. - # Here, the widget can still operate without input. - if segmentation is None: - self.inputSegmentationLength = 0 - else: - self.inputSegmentationLength = len(segmentation) - - # Display the standard message for "input changed". - self.infoBox.inputChanged()""" - def sendData(self): """Perform every required check and operation before calling the method that does the actual @@ -337,4 +309,4 @@ def onDeleteWidget(self): if __name__ == '__main__': - WidgetPreview(DemoTextableWidget).run() + WidgetPreview(DemoSciHub).run() diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index b77a592c..9a7ee1ff 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -107,7 +107,6 @@ class SciHubator(OWTextableBaseWidget): # ---------------------------------------------------------------------- # Channel definitions (NB: no input in this case)... - inputs = [] outputs = [('Text data', Segmentation)] # ---------------------------------------------------------------------- @@ -366,6 +365,8 @@ def processData(self): # Within this method, this is done using the following # instruction. self.signal_prog.emit(1, False) + + DOIs.append(self.DOIContent) # Indicate the total number of iterations that the # progress bar will go through (e.g. number of input From 82bd61bd4f9c284d923f66106a670be2f65bbbce Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:33:39 +0200 Subject: [PATCH 21/86] Update SCi-Hubator.rst change dependance --- specs/SCi-Hubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index 9ff83841..fffba8db 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -61,7 +61,7 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext =============== * Orange 3.38.1 * Orange Textable 3.2.2 -* `scihub.py `_ +* `scidownl `_ * PyMuPDF 1.25.4 (déjà présent pour SuperTextFiles) From 3d71a9fb7740b82aa8eba87a7256c3dbf3221a21 Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:38:15 +0200 Subject: [PATCH 22/86] Update SCi-Hubator.rst --- specs/SCi-Hubator.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index fffba8db..ed17bce1 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -61,8 +61,8 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext =============== * Orange 3.38.1 * Orange Textable 3.2.2 -* `scidownl `_ -* PyMuPDF 1.25.4 (déjà présent pour SuperTextFiles) +* `scidownl `_ 1.0.2 +* * `pdfplumber 0.11.6 `_ (déjà présent pour SuperTextFiles) 2.2 Fonctionnalités minimales From ef6b5ea98102747ef389addf74151c1e6ce0db43 Mon Sep 17 00:00:00 2001 From: ColinLug <114562993+ColinLug@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:38:47 +0200 Subject: [PATCH 23/86] Update SCi-Hubator.rst --- specs/SCi-Hubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index ed17bce1..ac1bec94 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -62,7 +62,7 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext * Orange 3.38.1 * Orange Textable 3.2.2 * `scidownl `_ 1.0.2 -* * `pdfplumber 0.11.6 `_ (déjà présent pour SuperTextFiles) +* `pdfplumber `_ 0.11.6 (déjà présent pour SuperTextFiles) 2.2 Fonctionnalités minimales From a351e36f6bfeaef17703e6798a3e5f7180d64fef Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 3 Apr 2025 10:40:46 +0200 Subject: [PATCH 24/86] =?UTF-8?q?Le=20widget=20prend=20un=20DOI=20et=20lit?= =?UTF-8?q?=20le=20fichier=20pdf=20t=C3=A9l=C3=A9charg=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../textable_prototypes/widgets/DemoSciHub.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index 79378ff7..0f69596f 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -27,6 +27,10 @@ from functools import partial import time +from scidownl import scihub_download +import tempfile +import pdfplumber +import os from _textable.widgets.TextableUtils import ( OWTextableBaseWidget, VersionedSettingsHandler, ProgressBar, @@ -42,6 +46,7 @@ from Orange.widgets import widget, gui, settings from Orange.widgets.utils.widgetpreview import WidgetPreview +from LTTL.Input import Input class DemoTextableWidget(OWTextableBaseWidget): @@ -209,7 +214,19 @@ def processData(self): # Update progress bar manually... self.signal_prog.emit(int(100*cur_itr/max_itr), False) cur_itr += 1 - + + # code ajouté ici + tempdir = tempfile.TemporaryDirectory() + paper = DOI + paper_type = "doi" + out = f"{tempdir.name}/{DOIList.index(DOI)}" + scihub_download(paper, paper_type=paper_type, out=out) + if os.path.exists(f"{out}.pdf"): + with pdfplumber.open(f"{out}.pdf") as pdf: + first_page = pdf.pages[0] + print(first_page.extract_text()) + ######## + # Create an LTTL.Input... if len(DOIList) == 1: # self.captionTitle is the name of the widget, From af0b06ed7f781655af61aa063f789b2a099138ef Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 3 Apr 2025 10:43:15 +0200 Subject: [PATCH 25/86] version GUI minimale DEMO --- orangecontrib/textable_prototypes/widgets/DemoSciHub.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index 0f69596f..db54d509 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -49,7 +49,7 @@ from LTTL.Input import Input -class DemoTextableWidget(OWTextableBaseWidget): +class DemoSciHUB(OWTextableBaseWidget): """Demo Orange3-Textable widget""" name = "Demo Scihub" @@ -75,7 +75,7 @@ class DemoTextableWidget(OWTextableBaseWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - + self.inputSegmentationLength = 0 # The following attribute is required by every widget # that imports new strings into Textable. self.createdInputs = list() From 66462adc96d6d339061aa940e884ecbef594f9cb Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 3 Apr 2025 11:53:47 +0200 Subject: [PATCH 26/86] Gestion d'erreurs --- .../textable_prototypes/widgets/DemoSciHub.py | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index db54d509..8f794f9f 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -155,7 +155,7 @@ def sendData(self): "warning") # Make sure to send None and return if the widget # cannot operate properly at this point. - self.send("New DOI", None) + self.send("New segmentation", None) return # If the widget creates new LTTL.Input objects (i.e. @@ -196,14 +196,14 @@ def processData(self): # instruction. self.signal_prog.emit(1, False) - DOIList = [] - DOIList.append(self.DOIContent) + DOIList = self.DOIContent.split(",") + #DOIList.append(self.DOIContent) # Indicate the total number of iterations that the # progress bar will go through (e.g. number of input # segments, number of selected files, etc.), then # set current iteration to 1. - max_itr = len(DOIList) + max_itr = len(DOIList)+1 cur_itr = 1 # Actual processing... @@ -220,11 +220,23 @@ def processData(self): paper = DOI paper_type = "doi" out = f"{tempdir.name}/{DOIList.index(DOI)}" - scihub_download(paper, paper_type=paper_type, out=out) + try: + scihub_download(paper, paper_type=paper_type, out=out) + except Exception as ex: + print(ex) + self.sendNoneToOutputs() + self.infoBox.setText(ex, 'error') + DOIText = "" if os.path.exists(f"{out}.pdf"): + print("plouf") with pdfplumber.open(f"{out}.pdf") as pdf: - first_page = pdf.pages[0] - print(first_page.extract_text()) + for page in pdf.pages: + DOIText += page.extract_text() + print(self.DOIContent) + else: + print("Bonjour") + self.sendNoneToOutputs() + self.infoBox.setText("Vérifiez la connextion", 'error') ######## # Create an LTTL.Input... @@ -235,7 +247,7 @@ def processData(self): label = self.captionTitle else: label = None # will be set later. - myInput = Input(self.DOIContent, label) + myInput = Input(DOIText, label) # Extract the first (and single) segment in the # newly created LTTL.Input and annotate it with From f352336166b29936924ce65009bf34f13e31c73b Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 3 Apr 2025 19:29:29 +0200 Subject: [PATCH 27/86] =?UTF-8?q?Gestion=20d'erreurs=20+=20progress=20bar?= =?UTF-8?q?=20+=20version=20minimale=20termin=C3=A9e=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../textable_prototypes/widgets/DemoSciHub.py | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index 8f794f9f..5304a5e6 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -31,6 +31,7 @@ import tempfile import pdfplumber import os +import requests from _textable.widgets.TextableUtils import ( OWTextableBaseWidget, VersionedSettingsHandler, ProgressBar, @@ -206,17 +207,22 @@ def processData(self): max_itr = len(DOIList)+1 cur_itr = 1 + # Permet de tester la connexion à Sci-Hub + if not test_scihub_accessible(): + self.sendNoneToOutputs() + self.infoBox.setText("SciHub inaccessible - vérifiez votre connexion", 'error') + return # Actual processing... # For each progress bar iteration... + tempdir = tempfile.TemporaryDirectory() for DOI in DOIList: # Update progress bar manually... self.signal_prog.emit(int(100*cur_itr/max_itr), False) - cur_itr += 1 + #cur_itr += 1 # code ajouté ici - tempdir = tempfile.TemporaryDirectory() paper = DOI paper_type = "doi" out = f"{tempdir.name}/{DOIList.index(DOI)}" @@ -228,15 +234,21 @@ def processData(self): self.infoBox.setText(ex, 'error') DOIText = "" if os.path.exists(f"{out}.pdf"): - print("plouf") - with pdfplumber.open(f"{out}.pdf") as pdf: - for page in pdf.pages: - DOIText += page.extract_text() - print(self.DOIContent) + try: + with pdfplumber.open(f"{out}.pdf") as pdf: + for page in pdf.pages: + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + cur_itr += (1/len(pdf.pages)) + DOIText += page.extract_text() + except Exception as e: + self.sendNoneToOutputs() + self.infoBox.setText(f"Erreur lors de la lecture du PDF: {str(e)}", 'error') + return else: print("Bonjour") self.sendNoneToOutputs() - self.infoBox.setText("Vérifiez la connextion", 'error') + self.infoBox.setText("Le téléchargement a échoué - vérifiez le DOI ou réessayez plus tard.", 'error') + return ######## # Create an LTTL.Input... @@ -247,6 +259,7 @@ def processData(self): label = self.captionTitle else: label = None # will be set later. + print(DOIText) myInput = Input(DOIText, label) # Extract the first (and single) segment in the @@ -267,8 +280,8 @@ def processData(self): time.sleep(0.00001) # Needed somehow! if self.cancel_operation: self.signal_prog.emit(100, False) - return - + return + tempdir.cleanup() # Update infobox and reset progress bar... self.signal_text.emit("Step 2/2: Post-processing...", "warning") @@ -337,5 +350,12 @@ def onDeleteWidget(self): self.clearCreatedInputs() +def test_scihub_accessible(): + try: + response = requests.get("https://sci-hub.se", timeout=10) + return response.status_code == 200 + except: + return False + if __name__ == '__main__': WidgetPreview(DemoSciHub).run() From 89e515e606c923b7f5b120877da05c3b5298b18e Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 10 Apr 2025 10:40:46 +0200 Subject: [PATCH 28/86] version GUI minimale DEMO --- orangecontrib/textable_prototypes/widgets/DemoSciHub.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index 5304a5e6..804c206e 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -266,8 +266,8 @@ def processData(self): # newly created LTTL.Input and annotate it with # the length of the input segmentation. segment = myInput[0] - segment.annotations["demo_annotation"] \ - = self.inputSegmentationLength + segment.annotations["DOI"] \ + = DOI # For the annotation to be saved in the LTTL.Input, # the extracted and annotated segment must be re-assigned # to the first (and only) segment of the LTTL.Input. From aa0b8cfb1a9e7405081aa2e804e4f07bdbb947f4 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 10 Apr 2025 11:12:35 +0200 Subject: [PATCH 29/86] =?UTF-8?q?2=20=C3=A9tapes=20+=20double=20barre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../textable_prototypes/widgets/DemoSciHub.py | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index 804c206e..fcb38ee4 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -204,13 +204,13 @@ def processData(self): # progress bar will go through (e.g. number of input # segments, number of selected files, etc.), then # set current iteration to 1. - max_itr = len(DOIList)+1 + max_itr = len(DOIList) cur_itr = 1 # Permet de tester la connexion à Sci-Hub if not test_scihub_accessible(): self.sendNoneToOutputs() - self.infoBox.setText("SciHub inaccessible - vérifiez votre connexion", 'error') + self.infoBox.setText("SciHub inaccessible - verify your connexion", 'error') return # Actual processing... @@ -220,7 +220,7 @@ def processData(self): # Update progress bar manually... self.signal_prog.emit(int(100*cur_itr/max_itr), False) - #cur_itr += 1 + cur_itr += 1 # code ajouté ici paper = DOI @@ -232,60 +232,64 @@ def processData(self): print(ex) self.sendNoneToOutputs() self.infoBox.setText(ex, 'error') + + # Update infobox and reset progress bar... + self.signal_text.emit("Step 2/2: Post-processing...", + "warning") + cur_itr = 0 + self.signal_prog.emit(0, True) + for DOI in DOIList: DOIText = "" - if os.path.exists(f"{out}.pdf"): + if os.path.exists(f"{tempdir.name}/{DOIList.index(DOI)}.pdf"): try: - with pdfplumber.open(f"{out}.pdf") as pdf: + with pdfplumber.open(f"{tempdir.name}/{DOIList.index(DOI)}.pdf") as pdf: for page in pdf.pages: self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - cur_itr += (1/len(pdf.pages)) + cur_itr += (1 / len(pdf.pages)) DOIText += page.extract_text() except Exception as e: self.sendNoneToOutputs() - self.infoBox.setText(f"Erreur lors de la lecture du PDF: {str(e)}", 'error') + self.infoBox.setText(f"Error occurred when reading PDF: {str(e)}", 'error') return else: print("Bonjour") self.sendNoneToOutputs() - self.infoBox.setText("Le téléchargement a échoué - vérifiez le DOI ou réessayez plus tard.", 'error') + self.infoBox.setText("Download failed. Please, verify DOI or connexion", 'error') return ######## - # Create an LTTL.Input... + # Create an LTTL.Input... if len(DOIList) == 1: # self.captionTitle is the name of the widget, # which will become the label of the output # segmentation. label = self.captionTitle else: - label = None # will be set later. + label = None # will be set later. print(DOIText) myInput = Input(DOIText, label) - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. segment = myInput[0] - segment.annotations["DOI"] \ + segment.annotations["DOI"] \ = DOI - # For the annotation to be saved in the LTTL.Input, + # For the annotation to be saved in the LTTL.Input, # the extracted and annotated segment must be re-assigned # to the first (and only) segment of the LTTL.Input. myInput[0] = segment - + # Add the LTTL.Input to self.createdInputs. self.createdInputs.append(myInput) - + # Cancel operation if requested by user... - time.sleep(0.00001) # Needed somehow! + time.sleep(0.00001) # Needed somehow! if self.cancel_operation: self.signal_prog.emit(100, False) return tempdir.cleanup() - # Update infobox and reset progress bar... - self.signal_text.emit("Step 2/2: Post-processing...", - "warning") - self.signal_prog.emit(1, True) + # If there's only one LTTL.Input created, it is the # widget's output... From e2ebba5fe8c5a1d90cf61403337b7a5f702b7edb Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 10 Apr 2025 11:13:53 +0200 Subject: [PATCH 30/86] preprocess et process --- orangecontrib/textable_prototypes/widgets/DemoSciHub.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index fcb38ee4..dd68d640 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -169,7 +169,7 @@ def sendData(self): # processing" and "post-processing" steps before and # after it. If there are no optional steps, notify # "Preprocessing...". - self.infoBox.setText("Step 1/2: Processing...", "warning") + self.infoBox.setText("Step 1/2: Pre-processing...", "warning") # Progress bar should be initialized at this point. self.progressBarInit() @@ -234,7 +234,7 @@ def processData(self): self.infoBox.setText(ex, 'error') # Update infobox and reset progress bar... - self.signal_text.emit("Step 2/2: Post-processing...", + self.signal_text.emit("Step 2/2: Processing...", "warning") cur_itr = 0 self.signal_prog.emit(0, True) From 05a7f1ba6d7c5a3f4b16a536f14df8b35e41afd4 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 10 Apr 2025 11:25:49 +0200 Subject: [PATCH 31/86] Gestion d'erreurs et cancel --- .../textable_prototypes/widgets/DemoSciHub.py | 10 ++++++++-- .../textable_prototypes/widgets/SciHubatorTest.py | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index dd68d640..7c33c214 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -27,8 +27,8 @@ from functools import partial import time -from scidownl import scihub_download import tempfile +from scidownl import scihub_download import pdfplumber import os import requests @@ -231,7 +231,13 @@ def processData(self): except Exception as ex: print(ex) self.sendNoneToOutputs() - self.infoBox.setText(ex, 'error') + self.infoBox.setText("An error occurred when downloading", 'error') + return + # Cancel operation if requested by user... + time.sleep(0.00001) # Needed somehow! + if self.cancel_operation: + self.signal_prog.emit(100, False) + return # Update infobox and reset progress bar... self.signal_text.emit("Step 2/2: Processing...", diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 9a7ee1ff..e7f262b5 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -28,7 +28,7 @@ # Standard imports... import re import http -from scihub import SciHub +from scidownl import scihub_download import pdfplumber from Orange.widgets import widget, gui, settings from Orange.widgets.utils.widgetpreview import WidgetPreview From ee895140733cb6a7f0fd75f1085ca9a4ee7ab18c Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 10 Apr 2025 11:37:19 +0200 Subject: [PATCH 32/86] scihub.png and .rst doc made (vcheck all TODOs) --- doc/widgets/SciHubator.rst | 245 ++++++++++++++++++ .../widgets/icons/scihubator.png | Bin 0 -> 8655 bytes 2 files changed, 245 insertions(+) create mode 100644 doc/widgets/SciHubator.rst create mode 100644 orangecontrib/textable_prototypes/widgets/icons/scihubator.png diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst new file mode 100644 index 00000000..92b8d0d1 --- /dev/null +++ b/doc/widgets/SciHubator.rst @@ -0,0 +1,245 @@ +sarah's note: searh for TODO for all missing and needing of correction areas +.. meta:: + :description: Orange3 Textable Prototypes documentation, SciHubator widget + :keywords: Orange3, Textable, Prototypes, documentation, SciHubator, widget + +.. _SciHubator: + +SciHubator +============== + +.. image:: figures/TODO.png + +Download pdf files from `Sci-HUB `_ and extract textual content into segmentations + +Authors +------- +Sarah Perreti-Poix, Borgeaud Matthias, Chétioui Orsowen, Luginbühl Colin + +Signals +------- + +Inputs: ``Message`` + + JSON Message controlling the list of imported text files TODO + + +Outputs: ``Text data`` + + Segmentation covering the content of downloaded pdf text files + +Requirements ???? TODO +------------------------- + +from functools import partial +import time +from scidownl import scihub_download +import tempfile +import pdfplumber +import os +import requests + + +Description +----------- + +This widget is designed to download pdf files from the SciHub project and outputs its content +into an annotated text segmentation. + + +Basic interface +~~~~~~~~~~~~~~~ + +In its basic version (see :ref:`figure 1 ` below), +the **SciHubator** widget is limited to the import of a single DOI. +The interface contains a **Source** section enabling the user to type the DOI. + +.. _SciHubator_basicinterface: + +.. figure:: figures/scihubator_basicinterface.png + :align: center + :alt: Basic interface of the SciHubator widget + + Figure 1: **SciHubator** widget (basic interface). + +Note that pdfplumber might not work properly with none latin alphabets +and serif typefaces. TODO + +The **Send** button triggers the emission of a segmentation to the output +connection(s). When it is selected, the **Send automatically** checkbox +disables the button and the widget attempts to automatically emit a +segmentation at every modification of its interface. + +The text below the **Send** button indicates the number TODO of characters in the single +segment contained in the output segmentation, or the reasons why no +segmentation is emitted (no input data, encoding issue, etc.). + +Advanced interface TODO +~~~~~~~~~~~~~~~~~~ + +The advanced version of **SciHubator** allows the user to import several DOIs +in a determined order; each outputed text file can moreover be segmented into +specific segmentations (introduction, mais corpus and bibliography) with specific +annotations. The emitted segmentation contains a segment +for each imported file. + +.. _scihubator_advancedinterface: + +.. figure:: figures/scihubator_advancedinterface.png + :align: center + :alt: Advanced interface of the Super Text files widget + :scale: 80% + + Figure 2: **SciHubator** widget (advanced interface). + +The advanced interface (see :ref:`figure 2 ` +above) presents similarities with that of the **URLs** and **Segment** +widgets. The **Sources** section allows the user to select the input +DOI(s). The list +of imported files appears at the top of the window; the columns of this list +indicate (a) the name of each file, (b) the corresponding annotation (if any), +and (c) the encoding with which each is associated. + +The first buttons on the right of the imported files' list enable the user to +modify the order in which they appear in the output segmentation (**Move Up** +and **Move Down**), to delete a file from the list (**Remove**) or to +completely empty it (**Clear All**). Except for **Clear All**, all these +buttons require the user to previously select an entry from the list. **Import +List** enables the user to import a file list in JSON format (see sections +*JSON im-/export format* and *File list* in Textable documentation) and to add +it to the previously selected sources. In the opposite **Export List** enables +the user to export the source list in a JSON +file. + +The remainder of the **Sources** section allows the user to add new files to +the list. The easiest way to do so is to first click on the **Browse** button, +which opens a file selection dialog. After having selected one or more files +in this dialog and validated the choice by clicking on **Open**, the files +appear in the **File paths** field and can be added to the list by clicking on +the **Add** button. It is also possible to type the complete paths of the +files directly in the text field, separating the paths corresponding to the +successive files with the string " \ " (space + slash + space). + +Before adding one or more files to the list by clicking on **Add**, it is +possible to select their encoding (**Encoding**), and to assign an annotation +by specifying its key in the **Annotation key** field and the corresponding +value in the **Annotation value** field. These three parameters (encoding, +key, value) will be applied to each file appearing in the **File paths** field +at the moment of their addition to the list with **Add**. + +The **PDF Password** field allows password-protected files to be passed to the widget. Insert the password in the field and proceed as usual. + +The **OCR Language(s)** field is needed by the OCR processes. By default, +it contains English abbreviated by `eng`. Multilingual files are supported +by complete the field with the languages separated by `+`. For example, +`eng+fra+ita`. See all `installable Tesseract data files +`_. If nothing is +indicated in this field, the language is assumed to be `eng`. + +**Force OCR** enables the OCR processes of the widget while also extracting textual content. Enable this if textual and image content are both present in the file (or if extraction of +textual content gives really bad results). + +The **Options** section allows the user to specify the label affected to the +output segmentation. The **Import filenames with key** checkbox enables the +program to create for each imported file an +annotation whose value is the file name (as displayed in the list) and whose +key is specified by the user in the text field on the right of the checkbox. +Similarly the button **Auto-number with key** enables the program to +automatically number the imported files and to associate the number to the +annotation key specified in the text field on the right. + + +The **Send** button triggers the emission of a segmentation to the output +connection(s). When it is selected, the **Send automatically** checkbox +disables the button and the widget attempts to automatically emit a +segmentation at every modification of its interface. + +The text below the **Send** button indicates the length of the output segmentation in +characters, or the reasons why no segmentation is emitted (no selected file, +encoding issue, etc.). In the example, the two segments corresponding to the +imported files thus total up to 1'262'145 characters. + +.. _text_files_remote_control_ref: + +Remote control +~~~~~~~~~~~~~~ + +**Super Text Files** is one the widgets that can be controlled by means of the +**Message** widget. Indeed, it can receive in input a message consisting +of a file list in JSON format (see sections *JSON im-/export format* and +*File list* in Textable documentation), in which case the list +of files specified in this message replaces previously imported sources (if +any). Note that removing the incoming connection from the **Message** instance +will not, by itself, remove the list of files imported in this way from the +**Super Text Files** instance's interface; conversely, this list of files can be +modified using buttons **Move up/down**, **Remove**, etc. even if the incoming +connection from the **Message** instance has not been removed. Finally, note +that if a **Super Text Files** instance has the basic version of its interface +activated when an incoming connection is created from an instance of +**Message**, it automatically switches to the advanced interface. + +Messages +-------- + +Information +~~~~~~~~~~~ + +*Data correctly sent to output: segments ( characters).* + This confirms that the widget has operated properly. + +*Settings were* (or *Input has*) *changed, please click 'Send' when ready.* + Settings and/or input have changed but the **Send automatically** checkbox + has not been selected, so the user is prompted to click the **Send** + button (or equivalently check the box) in order for computation and data + emission to proceed. + +*No data sent to output yet: no file selected.* + The widget instance is not able to emit data to output because no input + file has been selected. + +*No data sent to output yet, see 'Widget state' below.* + A problem with the instance's parameters and/or input data prevents it + from operating properly, and additional diagnostic information can be + found in the **Widget state** box at the bottom of the instance's + interface (see `Warnings`_ and `Errors`_ below). + +Warnings +~~~~~~~~ + +*No label was provided.* + A label must be entered in the **Output segmentation label** field in + order for computation and data emission to proceed. + +*No annotation key was provided for auto-numbering.* + The **Auto-number with key** checkbox has been selected and an annotation + key must be specified in the text field on the right in order for + computation and data emission to proceed. + +*JSON message on input connection doesn't have the right keys and/or values.* + The widget instance has received a JSON message on its ``Message`` input + channel and the keys and/or values specified in this message do not match + those that are expected for this particular widget type (see sections + *JSON im-/export format* and *File list* in Textable documentation). + +*JSON parsing error.* + The widget instance has received data on its ``Message`` input channel and + the data couldn't be correctly parsed. Please use a JSON validator to + check the data's well-formedness. + +Errors +~~~~~~ + +*Couldn't open file* or *Couldn't open file ''.* + A file couldn't be opened and read, typically because the specified path + is wrong. + +*Encoding error* or *Encoding error: file ''.* + A file couldn't be read with the specified encoding (it must be in another + encoding). + +*Please make sure all Tesseract parameter files for language(s) '' have been installed..* + One or more Tesseract language packages are probably missing. + +*Tesseract is not installed or it's not in your path.* + Add the directory where the tesseract-OCR binaries are located to the Environment Path variables, probably ``C:\Program Files\Tesseract-OCR`` + diff --git a/orangecontrib/textable_prototypes/widgets/icons/scihubator.png b/orangecontrib/textable_prototypes/widgets/icons/scihubator.png new file mode 100644 index 0000000000000000000000000000000000000000..d18166ac69d17c25b8a79096b803971c46800959 GIT binary patch literal 8655 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 Date: Thu, 10 Apr 2025 11:42:56 +0200 Subject: [PATCH 33/86] made inputs to none --- doc/widgets/SciHubator.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 92b8d0d1..e81dd8c1 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -1,4 +1,5 @@ sarah's note: searh for TODO for all missing and needing of correction areas + .. meta:: :description: Orange3 Textable Prototypes documentation, SciHubator widget :keywords: Orange3, Textable, Prototypes, documentation, SciHubator, widget @@ -19,14 +20,14 @@ Sarah Perreti-Poix, Borgeaud Matthias, Chétioui Orsowen, Luginbühl Colin Signals ------- -Inputs: ``Message`` +Inputs: ``None`` - JSON Message controlling the list of imported text files TODO + None Outputs: ``Text data`` - Segmentation covering the content of downloaded pdf text files + Segmentation covering the content of downloaded pdf files Requirements ???? TODO ------------------------- From 3ce320699bf3c57d8a1ba1179fba9b5d6efa8ddf Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 17 Apr 2025 10:35:03 +0200 Subject: [PATCH 34/86] enlever debugage --- orangecontrib/textable_prototypes/widgets/DemoSciHub.py | 1 - 1 file changed, 1 deletion(-) diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index 7c33c214..1214e096 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -258,7 +258,6 @@ def processData(self): self.infoBox.setText(f"Error occurred when reading PDF: {str(e)}", 'error') return else: - print("Bonjour") self.sendNoneToOutputs() self.infoBox.setText("Download failed. Please, verify DOI or connexion", 'error') return From ecf0397bf5f605247eafde0fb18d811de75936e7 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 17 Apr 2025 11:55:53 +0200 Subject: [PATCH 35/86] buttons working --- .../widgets/SciHubatorTest.py | 101 +++++++++--------- 1 file changed, 53 insertions(+), 48 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index e7f262b5..eda29fc5 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -28,6 +28,8 @@ # Standard imports... import re import http + +from PyQt5.QtWidgets import QMessageBox from scidownl import scihub_download import pdfplumber from Orange.widgets import widget, gui, settings @@ -228,7 +230,7 @@ def __init__(self): orientation='horizontal', label=u'DOI(s):', labelWidth=101, - callback=self.updateGUI, + callback=self.updateURLBoxButtons, tooltip=( u"The DOI(s) that will be added to the list when\n" u"button 'Add' is clicked.\n\n" @@ -473,9 +475,8 @@ def clearAll(self): del self.DOIs[:] del self.selectedURLLabel[:] self.sendButton.settingsChanged() - # Ne devrait pas être nécessaire non ? - # Rajoutée anyway - self.updateGUI() + self.URLLabel = self.URLLabel + self.clearAllButton.setDisabled(True) def remove(self): """Remove URL from DOIs attr""" @@ -484,62 +485,66 @@ def remove(self): self.DOIs.pop(index) del self.selectedURLLabel[:] self.sendButton.settingsChanged() - # Ne devrait pas être nécessaire non ? - # Rajoutée anyway - self.updateGUI() + self.URLLabel = self.URLLabel + self.clearAllButton.setDisabled(not bool(self.URLLabel)) def add(self): """Add DOIs to DOIs attr""" - DOIList = re.split(r'/', self.newDOI) + DOIList = re.split(r',', self.newDOI) print(DOIList) for DOI in DOIList: print(DOI) self.DOIs.append(DOI) - self.sendButton.settingsChanged() - # Ne devrait pas être nécessaire non ? - # Rajoutée anyway - self.updateGUI() - - def updateGUI(self): - """Update GUI state""" - # if self.selectedURLLabel: - # cachedLabel = self.selectedURLLabel[0] - # else: - # cachedLabel = None - del self.URLLabel[:] if self.DOIs: - DOIs = [f for f in self.DOIs] - self.URLLabel = DOIs - # maxURLLen = max([len(n) for n in DOIs]) - # for DOI in DOIs: #range(len(self.DOIs)): - # format = u'%-' + str(maxURLLen + 2) + u's' - #format % DOIs[index] - # self.URLLabel.append(DOI) + tempSet = set(self.DOIs) + if(len(tempSet) Date: Thu, 1 May 2025 10:57:35 +0200 Subject: [PATCH 36/86] supp function unused --- orangecontrib/textable_prototypes/widgets/SciHubatorTest.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index eda29fc5..db056abc 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -507,9 +507,6 @@ def add(self): self.URLLabel = self.URLLabel self.clearAllButton.setDisabled(not bool(self.DOIs)) self.sendButton.settingsChanged() - - def addDisabledOrNot(self): - self.addButton.setDisabled(not bool(self.newDOI)) # def updateGUI(self): # """Update GUI state""" From 00f10843cee2168e3e117c866d0140425adc62dc Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 1 May 2025 11:56:51 +0200 Subject: [PATCH 37/86] regex en commentaire dans DemoSciHub.py --- doc/widgets/SciHubator.rst | 2 +- orangecontrib/textable_prototypes/widgets/DemoSciHub.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index e81dd8c1..d6c8661d 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -1,4 +1,4 @@ -sarah's note: searh for TODO for all missing and needing of correction areas +sarah's note: search for TODO for all missing and needing of correction areas .. meta:: :description: Orange3 Textable Prototypes documentation, SciHubator widget diff --git a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py index 1214e096..84488f38 100644 --- a/orangecontrib/textable_prototypes/widgets/DemoSciHub.py +++ b/orangecontrib/textable_prototypes/widgets/DemoSciHub.py @@ -1,3 +1,5 @@ +#/(?<=\n)\n((biblio|r(e|é)f)\w*\W*\n)(.|\n)*/ +#/(Abstract.+?\n{1,})((.|\n)*)(?=\n\n)/gmi """ Class DemoTextableWidget Copyright 2025 University of Lausanne @@ -55,7 +57,7 @@ class DemoSciHUB(OWTextableBaseWidget): name = "Demo Scihub" description = "Export a text segmentation from a DOI or URL" - icon = "icons/someIcon.svg" + icon = "icons/scihubator.png" priority = 99 # Input and output channels (remove if not needed)... From c05a619e52ab4d43cfb63865bcb2aef7b5008418 Mon Sep 17 00:00:00 2001 From: Orsoladee <102214276+Orsoladee@users.noreply.github.com> Date: Thu, 1 May 2025 11:57:19 +0200 Subject: [PATCH 38/86] Update SciHubatorTest.py modif sendData --- .../widgets/SciHubatorTest.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index db056abc..f32c0d52 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -314,6 +314,43 @@ def sendData(self): before calling the method that does the actual processing. """ + # Verify DOIs + if not self.DOIContent.strip(): + self.infoBox.setText("Please enter one or many valid DOIs.", "warning") + self.send("New segmentation", None) + return + + #DOIs' validation + doi_list = [doi.strip() for doi in self.DOIContent.split(",") if doi.strip()] + if not doi_list: + self.infoBox.setText("No valid DOI detected", "warning") + self.send("New segmentation", None) + return + + # If the widget creates new LTTL.Input objects (i.e. + # if it imports new strings in Textable), make sure to + # clear previously created Inputs with this method. + self.clearCreatedInputs() + + # Notify processing in infobox. Typically, there should + # always be a "processing" step, with optional "pre- + # processing" and "post-processing" steps before and + # after it. If there are no optional steps, notify + # "Preprocessing...". + self.infoBox.setText("Step 1/2: Processing...", "warning") + + # Progress bar should be initialized at this point. + self.progressBarInit() + + # Create a threaded function to do the actual processing + # and specify its arguments (here there are none). + threaded_function = partial( + self.processData, + # argument1, + # argument2, + # ... + ) + if self.DOI == "": # Use mode "warning" when user needs to do some From ac7feb3dc061fa9ee593c5fdd543a5ceac0ac612 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 8 May 2025 10:30:46 +0200 Subject: [PATCH 39/86] specs --- specs/SCi-Hubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst index ac1bec94..222ce3c0 100644 --- a/specs/SCi-Hubator.rst +++ b/specs/SCi-Hubator.rst @@ -89,7 +89,7 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext * créer et émettre une segmentation par thème. * créer et émettre un résumé/abstract. * créer et émettre un tableau de cross-reference. -* importer un JSON contenant des nombreux liens +* importer un JSON contenant plusieurs DOI. 2.5 Tests ========= From 539acb5822b1af91c7a13bebfb200d1b7717753e Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 8 May 2025 10:53:16 +0200 Subject: [PATCH 40/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index d6c8661d..466cc9a1 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -78,7 +78,7 @@ segmentation is emitted (no input data, encoding issue, etc.). Advanced interface TODO ~~~~~~~~~~~~~~~~~~ -The advanced version of **SciHubator** allows the user to import several DOIs +The advanced version of **SciHubator** allows the user to type several DOIs in a determined order; each outputed text file can moreover be segmented into specific segmentations (introduction, mais corpus and bibliography) with specific annotations. The emitted segmentation contains a segment From 5400b1a772d2edd8fcdf82db86b483465e1a9503 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 8 May 2025 10:55:46 +0200 Subject: [PATCH 41/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 466cc9a1..da71b76f 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -57,7 +57,7 @@ The interface contains a **Source** section enabling the user to type the DOI. .. _SciHubator_basicinterface: -.. figure:: figures/scihubator_basicinterface.png +.. figure:: specs/images/scihubator_minimal.png :align: center :alt: Basic interface of the SciHubator widget From e210d6457f6a504d79fe22795152c19a367d431a Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 8 May 2025 11:00:40 +0200 Subject: [PATCH 42/86] update like demo --- .../widgets/SciHubatorTest.py | 182 +++++++++--------- 1 file changed, 94 insertions(+), 88 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index f32c0d52..f400c314 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -32,6 +32,11 @@ from PyQt5.QtWidgets import QMessageBox from scidownl import scihub_download import pdfplumber +import requests +import time +import tempfile +import os +from functools import partial from Orange.widgets import widget, gui, settings from Orange.widgets.utils.widgetpreview import WidgetPreview from Orange.widgets.settings import Setting @@ -315,70 +320,20 @@ def sendData(self): processing. """ # Verify DOIs - if not self.DOIContent.strip(): + if not self.DOIs: self.infoBox.setText("Please enter one or many valid DOIs.", "warning") self.send("New segmentation", None) return - - #DOIs' validation - doi_list = [doi.strip() for doi in self.DOIContent.split(",") if doi.strip()] - if not doi_list: - self.infoBox.setText("No valid DOI detected", "warning") - self.send("New segmentation", None) - return - - # If the widget creates new LTTL.Input objects (i.e. - # if it imports new strings in Textable), make sure to - # clear previously created Inputs with this method. - self.clearCreatedInputs() - - # Notify processing in infobox. Typically, there should - # always be a "processing" step, with optional "pre- - # processing" and "post-processing" steps before and - # after it. If there are no optional steps, notify - # "Preprocessing...". - self.infoBox.setText("Step 1/2: Processing...", "warning") - - # Progress bar should be initialized at this point. - self.progressBarInit() - - # Create a threaded function to do the actual processing - # and specify its arguments (here there are none). - threaded_function = partial( - self.processData, - # argument1, - # argument2, - # ... - ) - - - if self.DOI == "": - # Use mode "warning" when user needs to do some - # action or provide some information; use mode "error" - # when invalid parameters have been provided; - # for notifications that don't require user action, - # don't use a mode. Use formulations that emphasize - # what should be done rather than what is wrong or - # missing. - self.infoBox.setText("Please type DOI.", - "warning") - # Make sure to send None and return if the widget - # cannot operate properly at this point. - self.send("New segmentation", None) - return - # If the widget creates new LTTL.Input objects (i.e. - # if it imports new strings in Textable), make sure to - # clear previously created Inputs with this method. self.clearCreatedInputs() # Notify processing in infobox. Typically, there should # always be a "processing" step, with optional "pre- - # processing" and "post-processing" steps before and - # after it. If there are no optional steps, notify + # processing" and "post-processing" steps before and + # after it. If there are no optional steps, notify # "Preprocessing...". - self.infoBox.setText("Step 1/2: Processing...", "warning") - + self.infoBox.setText("Step 1/2: Pre-processing...", "warning") + # Progress bar should be initialized at this point. self.progressBarInit() @@ -386,8 +341,8 @@ def sendData(self): # and specify its arguments (here there are none). threaded_function = partial( self.processData, - # argument1, - # argument2, + # argument1, + # argument2, # ... ) @@ -405,72 +360,116 @@ def processData(self): # instruction. self.signal_prog.emit(1, False) - DOIs.append(self.DOIContent) - + # DOIList.append(self.DOIContent) + # Indicate the total number of iterations that the # progress bar will go through (e.g. number of input # segments, number of selected files, etc.), then # set current iteration to 1. - max_itr = int(self.numberOfSegments) + max_itr = len(self.DOIs) cur_itr = 1 + # Permet de tester la connexion à Sci-Hub + if not test_scihub_accessible(): + self.sendNoneToOutputs() + self.infoBox.setText("SciHub inaccessible - verify your connexion", 'error') + return # Actual processing... - + # For each progress bar iteration... - for _ in range(int(self.numberOfSegments)): + tempdir = tempfile.TemporaryDirectory() + for DOI in self.DOIs: # Update progress bar manually... - self.signal_prog.emit(int(100*cur_itr/max_itr), False) + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) cur_itr += 1 - - # Create an LTTL.Input... - if int(self.numberOfSegments) == 1: + + # code ajouté ici + paper = DOI + paper_type = "doi" + out = f"{tempdir.name}/{self.DOIs.index(DOI)}" + try: + scihub_download(paper, paper_type=paper_type, out=out) + except Exception as ex: + print(ex) + self.sendNoneToOutputs() + self.infoBox.setText("An error occurred when downloading", 'error') + return + # Cancel operation if requested by user... + time.sleep(0.00001) # Needed somehow! + if self.cancel_operation: + self.signal_prog.emit(100, False) + return + + # Update infobox and reset progress bar... + self.signal_text.emit("Step 2/2: Processing...", + "warning") + cur_itr = 0 + self.signal_prog.emit(0, True) + for DOI in self.DOIs: + DOIText = "" + if os.path.exists(f"{tempdir.name}/{self.DOIs.index(DOI)}.pdf"): + try: + with pdfplumber.open(f"{tempdir.name}/{self.DOIs.index(DOI)}.pdf") as pdf: + for page in pdf.pages: + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + cur_itr += (1 / len(pdf.pages)) + DOIText += page.extract_text() + except Exception as e: + self.sendNoneToOutputs() + self.infoBox.setText(f"Error occurred when reading PDF: {str(e)}", 'error') + return + else: + self.sendNoneToOutputs() + self.infoBox.setText("Download failed. Please, verify DOI or connexion", 'error') + return + ######## + + # Create an LTTL.Input... + if len(self.DOIs) == 1: # self.captionTitle is the name of the widget, # which will become the label of the output # segmentation. label = self.captionTitle else: - label = None # will be set later. - myInput = Input(self.segmentContent, label) + label = None # will be set later. + print(DOIText) + myInput = Input(DOIText, label) - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. segment = myInput[0] - segment.annotations["demo_annotation"] \ - = self.inputSegmentationLength - # For the annotation to be saved in the LTTL.Input, + segment.annotations["DOI"] \ + = DOI + # For the annotation to be saved in the LTTL.Input, # the extracted and annotated segment must be re-assigned # to the first (and only) segment of the LTTL.Input. myInput[0] = segment - + # Add the LTTL.Input to self.createdInputs. self.createdInputs.append(myInput) - + # Cancel operation if requested by user... - time.sleep(0.00001) # Needed somehow! + time.sleep(0.00001) # Needed somehow! if self.cancel_operation: self.signal_prog.emit(100, False) - return - - # Update infobox and reset progress bar... - self.signal_text.emit("Step 2/2: Post-processing...", - "warning") - self.signal_prog.emit(1, True) + return + tempdir.cleanup() - # If there's only one LTTL.Input created, it is the + # If there's only one LTTL.Input created, it is the # widget's output... - if int(self.numberOfSegments) == 1: + if len(self.DOIs) == 1: return self.createdInputs[0] - # Otherwise the widget's output is a concatenation... + # Otherwise the widget's output is a concatenation... else: return Segmenter.concatenate( caller=self, segmentations=self.createdInputs, label=self.captionTitle, import_labels_as=None, - ) + ) @OWTextableBaseWidget.task_decorator def task_finished(self, f): @@ -527,8 +526,9 @@ def remove(self): def add(self): """Add DOIs to DOIs attr""" - DOIList = re.split(r',', self.newDOI) + DOIList = [x.strip() for x in self.newDOI.strip().split(',')] print(DOIList) + #Pas besoin de la boucle DOIList for DOI in DOIList: print(DOI) self.DOIs.append(DOI) @@ -593,6 +593,12 @@ def clearCreatedInputs(self): def onDeleteWidget(self): """Clear created inputs on widget deletion""" self.clearCreatedInputs() +def test_scihub_accessible(): + try: + response = requests.get("https://sci-hub.se", timeout=10) + return response.status_code == 200 + except: + return False if __name__ == '__main__': WidgetPreview(SciHubator).run() From a013424aa3dc63334e93d4de576c56a4973ebb4e Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 8 May 2025 11:22:23 +0200 Subject: [PATCH 43/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 93 +------------------------------------- 1 file changed, 1 insertion(+), 92 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index da71b76f..eadb7b00 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -105,50 +105,7 @@ The first buttons on the right of the imported files' list enable the user to modify the order in which they appear in the output segmentation (**Move Up** and **Move Down**), to delete a file from the list (**Remove**) or to completely empty it (**Clear All**). Except for **Clear All**, all these -buttons require the user to previously select an entry from the list. **Import -List** enables the user to import a file list in JSON format (see sections -*JSON im-/export format* and *File list* in Textable documentation) and to add -it to the previously selected sources. In the opposite **Export List** enables -the user to export the source list in a JSON -file. - -The remainder of the **Sources** section allows the user to add new files to -the list. The easiest way to do so is to first click on the **Browse** button, -which opens a file selection dialog. After having selected one or more files -in this dialog and validated the choice by clicking on **Open**, the files -appear in the **File paths** field and can be added to the list by clicking on -the **Add** button. It is also possible to type the complete paths of the -files directly in the text field, separating the paths corresponding to the -successive files with the string " \ " (space + slash + space). - -Before adding one or more files to the list by clicking on **Add**, it is -possible to select their encoding (**Encoding**), and to assign an annotation -by specifying its key in the **Annotation key** field and the corresponding -value in the **Annotation value** field. These three parameters (encoding, -key, value) will be applied to each file appearing in the **File paths** field -at the moment of their addition to the list with **Add**. - -The **PDF Password** field allows password-protected files to be passed to the widget. Insert the password in the field and proceed as usual. - -The **OCR Language(s)** field is needed by the OCR processes. By default, -it contains English abbreviated by `eng`. Multilingual files are supported -by complete the field with the languages separated by `+`. For example, -`eng+fra+ita`. See all `installable Tesseract data files -`_. If nothing is -indicated in this field, the language is assumed to be `eng`. - -**Force OCR** enables the OCR processes of the widget while also extracting textual content. Enable this if textual and image content are both present in the file (or if extraction of -textual content gives really bad results). - -The **Options** section allows the user to specify the label affected to the -output segmentation. The **Import filenames with key** checkbox enables the -program to create for each imported file an -annotation whose value is the file name (as displayed in the list) and whose -key is specified by the user in the text field on the right of the checkbox. -Similarly the button **Auto-number with key** enables the program to -automatically number the imported files and to associate the number to the -annotation key specified in the text field on the right. - +buttons require the user to previously select an entry from the list. The **Send** button triggers the emission of a segmentation to the output connection(s). When it is selected, the **Send automatically** checkbox @@ -160,25 +117,6 @@ characters, or the reasons why no segmentation is emitted (no selected file, encoding issue, etc.). In the example, the two segments corresponding to the imported files thus total up to 1'262'145 characters. -.. _text_files_remote_control_ref: - -Remote control -~~~~~~~~~~~~~~ - -**Super Text Files** is one the widgets that can be controlled by means of the -**Message** widget. Indeed, it can receive in input a message consisting -of a file list in JSON format (see sections *JSON im-/export format* and -*File list* in Textable documentation), in which case the list -of files specified in this message replaces previously imported sources (if -any). Note that removing the incoming connection from the **Message** instance -will not, by itself, remove the list of files imported in this way from the -**Super Text Files** instance's interface; conversely, this list of files can be -modified using buttons **Move up/down**, **Remove**, etc. even if the incoming -connection from the **Message** instance has not been removed. Finally, note -that if a **Super Text Files** instance has the basic version of its interface -activated when an incoming connection is created from an instance of -**Message**, it automatically switches to the advanced interface. - Messages -------- @@ -210,37 +148,8 @@ Warnings *No label was provided.* A label must be entered in the **Output segmentation label** field in order for computation and data emission to proceed. - -*No annotation key was provided for auto-numbering.* - The **Auto-number with key** checkbox has been selected and an annotation - key must be specified in the text field on the right in order for - computation and data emission to proceed. - -*JSON message on input connection doesn't have the right keys and/or values.* - The widget instance has received a JSON message on its ``Message`` input - channel and the keys and/or values specified in this message do not match - those that are expected for this particular widget type (see sections - *JSON im-/export format* and *File list* in Textable documentation). - -*JSON parsing error.* - The widget instance has received data on its ``Message`` input channel and - the data couldn't be correctly parsed. Please use a JSON validator to - check the data's well-formedness. Errors ~~~~~~ -*Couldn't open file* or *Couldn't open file ''.* - A file couldn't be opened and read, typically because the specified path - is wrong. - -*Encoding error* or *Encoding error: file ''.* - A file couldn't be read with the specified encoding (it must be in another - encoding). - -*Please make sure all Tesseract parameter files for language(s) '' have been installed..* - One or more Tesseract language packages are probably missing. - -*Tesseract is not installed or it's not in your path.* - Add the directory where the tesseract-OCR binaries are located to the Environment Path variables, probably ``C:\Program Files\Tesseract-OCR`` From 38c1a4d4b560edae378c4c4b8031de142bef5b97 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 8 May 2025 11:23:23 +0200 Subject: [PATCH 44/86] import cleaned (a bit) and tasked working --- .../widgets/SciHubatorTest.py | 71 +++++++++---------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index f400c314..63ed3f94 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -26,29 +26,25 @@ __email__ = "aris.xanthos@unil.ch" # Standard imports... -import re -import http - -from PyQt5.QtWidgets import QMessageBox -from scidownl import scihub_download -import pdfplumber -import requests import time import tempfile +import pdfplumber import os +import requests +import LTTL.SegmenterThread as Segmenter + from functools import partial -from Orange.widgets import widget, gui, settings -from Orange.widgets.utils.widgetpreview import WidgetPreview -from Orange.widgets.settings import Setting +from scidownl import scihub_download from _textable.widgets.TextableUtils import ( OWTextableBaseWidget, VersionedSettingsHandler, ProgressBar, - JSONMessage, InfoBox, SendButton, AdvancedSettings, - addSeparatorAfterDefaultEncodings, addAutoDetectEncoding, - normalizeCarriageReturns, getPredefinedEncodings, pluralize + InfoBox, SendButton, pluralize, Task ) from LTTL.Segmentation import Segmentation - - +from Orange.widgets import widget, gui, settings +from Orange.widgets.utils.widgetpreview import WidgetPreview +from LTTL.Input import Input +from Orange.widgets.settings import Setting +from PyQt5.QtWidgets import QMessageBox class SciHubator(OWTextableBaseWidget): """An Orange widget that lets the user select an integer value""" @@ -114,7 +110,7 @@ class SciHubator(OWTextableBaseWidget): # ---------------------------------------------------------------------- # Channel definitions (NB: no input in this case)... - outputs = [('Text data', Segmentation)] + outputs = [('Segmentation', Segmentation)] # ---------------------------------------------------------------------- # GUI layout parameters... @@ -322,7 +318,7 @@ def sendData(self): # Verify DOIs if not self.DOIs: self.infoBox.setText("Please enter one or many valid DOIs.", "warning") - self.send("New segmentation", None) + self.send("Segmentation", None) return self.clearCreatedInputs() @@ -433,7 +429,6 @@ def processData(self): label = self.captionTitle else: label = None # will be set later. - print(DOIText) myInput = Input(DOIText, label) # Extract the first (and single) segment in the @@ -473,25 +468,25 @@ def processData(self): @OWTextableBaseWidget.task_decorator def task_finished(self, f): - """All operations following the successful termination - of self.processData - """ - - # Get the result value of self.processData. - processed_data = f.result() - - # If it is not None... - if processed_data: - message = f"{len(processed_data)} segment@p sent to output " - message = pluralize(message, len(processed_data)) - numChars = 0 - for segment in processed_data: - segmentLength = len(Segmentation.get_data(segment.str_index)) - numChars += segmentLength - message += f"({numChars} character@p)." - message = pluralize(message, numChars) - self.infoBox.setText(message) - self.send("New segmentation", processed_data) + """All operations following the successful termination + of self.processData + """ + + # Get the result value of self.processData. + processed_data = f.result() + + # If it is not None... + if processed_data: + message = "Text sent to output " + message = pluralize(message, len(processed_data)) + """numChars = 0 + for segment in processed_data: + segmentLength = len(Segmentation.get_data(segment.str_index)) + numChars += segmentLength + message += f"({numChars} character@p)." + message = pluralize(message, numChars)""" + self.infoBox.setText(message) + self.send("Segmentation", processed_data) # The following method should be copied verbatim in # every Textable widget. @@ -528,7 +523,7 @@ def add(self): """Add DOIs to DOIs attr""" DOIList = [x.strip() for x in self.newDOI.strip().split(',')] print(DOIList) - #Pas besoin de la boucle DOIList + #--> Pas besoin de la boucle DOIList non?? <-- for DOI in DOIList: print(DOI) self.DOIs.append(DOI) From eec66e2ff682eec6679a7c447ab4e3135a6d510a Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 8 May 2025 11:29:14 +0200 Subject: [PATCH 45/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index eadb7b00..7b736654 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -32,15 +32,16 @@ Outputs: ``Text data`` Requirements ???? TODO ------------------------- -from functools import partial -import time -from scidownl import scihub_download -import tempfile -import pdfplumber -import os -import requests - - +* Orange 3.38.1 +* Orange Textable 3.2.2 +* from functools import partial +* import time +* from scidownl import scihub_download +* import tempfile +* import pdfplumber +* import os +* import requests + Description ----------- From 86e972dbea91d55aef5f6defd7090a911693ec27 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 8 May 2025 11:29:49 +0200 Subject: [PATCH 46/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 7b736654..2389baad 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -29,8 +29,8 @@ Outputs: ``Text data`` Segmentation covering the content of downloaded pdf files -Requirements ???? TODO -------------------------- +Requirements +------------ * Orange 3.38.1 * Orange Textable 3.2.2 From 9836f3a3833540edad892fd7ca49899d0aaa0caf Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 8 May 2025 11:35:16 +0200 Subject: [PATCH 47/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 2389baad..973ae7e0 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -150,6 +150,18 @@ Warnings A label must be entered in the **Output segmentation label** field in order for computation and data emission to proceed. +*Please enter one or many valid DOIs.* + +*No valid DOI detected.* + +*Step 1/2: Processing...* + +*Step 2/2: Post-processing...* + +*Please type DOI.* + + + Errors ~~~~~~ From fe9346ed19853791a4a50dcd4afc1c0075e05e4c Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 8 May 2025 11:50:02 +0200 Subject: [PATCH 48/86] =?UTF-8?q?jsp=20mais=20r=C3=A9paration=20des=20clea?= =?UTF-8?q?rAll?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/SciHubatorTest.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 63ed3f94..499f0399 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -139,12 +139,11 @@ class SciHubator(OWTextableBaseWidget): def __init__(self): super().__init__() - self.URLLabel = list() + self.URLLabel = self.DOIs[:] self.selectedURLLabel = list() self.newDOI = u'' self.extractedText = u'' self.DOI = u'' - self.DOIs = list() self.createdInputs = list() self.infoBox = InfoBox(widget=self.controlArea) @@ -309,10 +308,10 @@ def __init__(self): self.sendButton.draw() self.infoBox.draw() self.sendButton.sendIf() - + def sendData(self): - """Perform every required check and operation - before calling the method that does the actual + """Perform every required check and operation + before calling the method that does the actual processing. """ # Verify DOIs @@ -350,7 +349,7 @@ def processData(self): which is run in a worker thread so that GUI stays responsive and operations can be cancelled """ - + # At start of processing, set progress bar to 1%. # Within this method, this is done using the following # instruction. @@ -488,7 +487,7 @@ def task_finished(self, f): self.infoBox.setText(message) self.send("Segmentation", processed_data) - # The following method should be copied verbatim in + # The following method should be copied verbatim in # every Textable widget. def setCaption(self, title): """Register captionTitle changes and send if needed""" @@ -506,8 +505,9 @@ def clearAll(self): del self.DOIs[:] del self.selectedURLLabel[:] self.sendButton.settingsChanged() - self.URLLabel = self.URLLabel + self.URLLabel = self.DOIs self.clearAllButton.setDisabled(True) + self.removeButton.setDisabled(True) def remove(self): """Remove URL from DOIs attr""" @@ -576,7 +576,7 @@ def updateURLBoxButtons(self): self.removeButton.setDisabled(not bool(self.selectedURLLabel)) - # The following two methods should be copied verbatim in + # The following two methods should be copied verbatim in # every Textable widget that creates LTTL.Input objects. def clearCreatedInputs(self): @@ -598,7 +598,7 @@ def test_scihub_accessible(): if __name__ == '__main__': WidgetPreview(SciHubator).run() - + # def clearAll(self): # """Remove all DOIs from DOIs attr""" # del self.DOIs[:] From 503abb291b60248d57445947e52301a126c39f71 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 8 May 2025 13:47:19 +0200 Subject: [PATCH 49/86] updated processing and saving settings --- .../widgets/SciHubatorTest.py | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 499f0399..6cdfe504 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -140,6 +140,7 @@ class SciHubator(OWTextableBaseWidget): def __init__(self): super().__init__() self.URLLabel = self.DOIs[:] + print(self.URLLabel) self.selectedURLLabel = list() self.newDOI = u'' self.extractedText = u'' @@ -305,6 +306,8 @@ def __init__(self): disabled = True, ) gui.rubber(self.controlArea) + self.URLLabel = self.URLLabel + self.updateURLBoxButtons() self.sendButton.draw() self.infoBox.draw() self.sendButton.sendIf() @@ -327,7 +330,7 @@ def sendData(self): # processing" and "post-processing" steps before and # after it. If there are no optional steps, notify # "Preprocessing...". - self.infoBox.setText("Step 1/2: Pre-processing...", "warning") + self.infoBox.setText(f"Step 1/3: Pre-processing...", "warning") # Progress bar should be initialized at this point. self.progressBarInit() @@ -397,7 +400,7 @@ def processData(self): return # Update infobox and reset progress bar... - self.signal_text.emit("Step 2/2: Processing...", + self.signal_text.emit(f"Step 2/3: Processing...", "warning") cur_itr = 0 self.signal_prog.emit(0, True) @@ -451,6 +454,27 @@ def processData(self): return tempdir.cleanup() + #Ajouter les regex + + if(not self.importAll and (self.importAbstract or self.importText or self.importBibliography)): + self.signal_text.emit("Step 3/3: Post-processing...", + "warning") + cur_itr = 0 + self.signal_prog.emit(0, True) + max_itr = int(self.importAll) + int(self.importText) + int(self.importBibliography) + int(self.importAbstract) + + if(self.importAbstract): + regex = r'/(Abstract.+?\n{1,})((.|\n)*)(?=\n\n)/gmi' + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + + if(self.importText): + regex = r'???' + + if(self.importBibliography): + regex = r'#/(?<=\n)\n((biblio|r(e|é)f)\w*\W*\n)(.|\n)*/' + + + # If there's only one LTTL.Input created, it is the # widget's output... if len(self.DOIs) == 1: @@ -574,6 +598,7 @@ def updateURLBoxButtons(self): """Update state of File box buttons""" self.addButton.setDisabled(not bool(self.newDOI)) self.removeButton.setDisabled(not bool(self.selectedURLLabel)) + self.clearAllButton.setDisabled(not bool(self.URLLabel)) # The following two methods should be copied verbatim in From 63c0ea021b6aa3b667eb1c4457b677f2702906c1 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Fri, 9 May 2025 12:09:21 +0200 Subject: [PATCH 50/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 973ae7e0..903f2f2c 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -151,6 +151,7 @@ Warnings order for computation and data emission to proceed. *Please enter one or many valid DOIs.* + A valid DOI is required for being processed by Sci-Hub. *No valid DOI detected.* @@ -165,4 +166,14 @@ Warnings Errors ~~~~~~ +*SciHub inaccessible - verify your connexion.* + +*An error occurred when downloading.* + +*Error occurred when reading PDF:* + +*Download failed. Please, verify DOI or connexion.* + + + From 478eb438e57a838d0cbe07c13e95c30ccedbf157 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Wed, 14 May 2025 11:57:02 +0200 Subject: [PATCH 51/86] j'ai mis mon nom correctment c'est tout --- doc/widgets/SciHubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 903f2f2c..b6c10aee 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -15,7 +15,7 @@ Download pdf files from `Sci-HUB `_ and extract textual Authors ------- -Sarah Perreti-Poix, Borgeaud Matthias, Chétioui Orsowen, Luginbühl Colin +Peretti-Poix Sarah, Borgeaud Matthias, Chétioui Orsowen, Luginbühl Colin Signals ------- From 3ba138ab1e565a98e2a1220cfec04cf893c5e9e7 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 15 May 2025 10:35:07 +0200 Subject: [PATCH 52/86] truc --- .../textable_prototypes/widgets/SciHubatorTest.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 6cdfe504..9e498fbc 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -456,21 +456,22 @@ def processData(self): #Ajouter les regex - if(not self.importAll and (self.importAbstract or self.importText or self.importBibliography)): + if not self.importAll and (self.importAbstract or self.importText or self.importBibliography): self.signal_text.emit("Step 3/3: Post-processing...", "warning") cur_itr = 0 self.signal_prog.emit(0, True) max_itr = int(self.importAll) + int(self.importText) + int(self.importBibliography) + int(self.importAbstract) - if(self.importAbstract): - regex = r'/(Abstract.+?\n{1,})((.|\n)*)(?=\n\n)/gmi' + if self.importAbstract: + regexes = [(r'/(Abstract.+?\n{1,})((.|\n)*)(?=\n\n)/gmi', "tokenize")] self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + new_segmentation = tokenize(myInput, regexes) - if(self.importText): + if self.importText: regex = r'???' - if(self.importBibliography): + if self.importBibliography: regex = r'#/(?<=\n)\n((biblio|r(e|é)f)\w*\W*\n)(.|\n)*/' From 373fe5ac90f8e5e2bb5bd2465ee37a43a7e0b15e Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 15 May 2025 10:51:16 +0200 Subject: [PATCH 53/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index b6c10aee..c2b90050 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -58,7 +58,7 @@ The interface contains a **Source** section enabling the user to type the DOI. .. _SciHubator_basicinterface: -.. figure:: specs/images/scihubator_minimal.png +.. figure:: https://github.com/sarahperettipoix/orange3-textable-prototypes/blob/master/specs/images/scihubator_minimal.png :align: center :alt: Basic interface of the SciHubator widget @@ -76,7 +76,7 @@ The text below the **Send** button indicates the number TODO of characters in th segment contained in the output segmentation, or the reasons why no segmentation is emitted (no input data, encoding issue, etc.). -Advanced interface TODO +Advanced interface ~~~~~~~~~~~~~~~~~~ The advanced version of **SciHubator** allows the user to type several DOIs From 78ee0d1a30faf6ae3cc86825ac311997c65c73f7 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 15 May 2025 10:53:34 +0200 Subject: [PATCH 54/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index c2b90050..9d8fbebc 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -87,7 +87,7 @@ for each imported file. .. _scihubator_advancedinterface: -.. figure:: figures/scihubator_advancedinterface.png +.. figure:: https://github.com/sarahperettipoix/orange3-textable-prototypes/blob/master/specs/images/scihubator_principal.png :align: center :alt: Advanced interface of the Super Text files widget :scale: 80% From 02432ff4fe6e0a4706f633c80e8d776cbedbe259 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 15 May 2025 11:18:11 +0200 Subject: [PATCH 55/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 9d8fbebc..58f411cc 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -146,20 +146,16 @@ Information Warnings ~~~~~~~~ -*No label was provided.* - A label must be entered in the **Output segmentation label** field in - order for computation and data emission to proceed. - *Please enter one or many valid DOIs.* - A valid DOI is required for being processed by Sci-Hub. + A valid DOI is required for being processed by Sci-Hub. The warning indicates that nothing was typed in the DOI field. -*No valid DOI detected.* +*Step 1/3: Pre-processing...* + +*Step 2/3: Processing...* -*Step 1/2: Processing...* +*Step 3/3: Post-processing...* -*Step 2/2: Post-processing...* -*Please type DOI.* @@ -167,13 +163,16 @@ Errors ~~~~~~ *SciHub inaccessible - verify your connexion.* + Plese verify your internet connexion or check if Sci-Hub is down. *An error occurred when downloading.* + Donwloading the PDF didn't worked, please try again. *Error occurred when reading PDF:* + An unexpected error occured when reading the downloaded PDF. Please try again, if the error still happen your DOI could be not compatible. *Download failed. Please, verify DOI or connexion.* - + Sci-Hub is accessible but scihubator couldn't download the PDF. Your connexion has perhaps crashed in the download process or the DOI provided is not valid. From 51fa219128af76aa8fc3120cb990d377906e4397 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 15 May 2025 11:30:42 +0200 Subject: [PATCH 56/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 58f411cc..39c39098 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -150,11 +150,11 @@ Warnings A valid DOI is required for being processed by Sci-Hub. The warning indicates that nothing was typed in the DOI field. *Step 1/3: Pre-processing...* - + The PDF is being downloaded *Step 2/3: Processing...* - + The PDF is being processed into a raw text. *Step 3/3: Post-processing...* - + Segmentations are applied to the text. From 7a1726577919d365449461351acec093d01020d5 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 15 May 2025 11:34:56 +0200 Subject: [PATCH 57/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 39c39098..4e8cc888 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -163,7 +163,7 @@ Errors ~~~~~~ *SciHub inaccessible - verify your connexion.* - Plese verify your internet connexion or check if Sci-Hub is down. + Plese verify your internet connexion or check if `Sci-HUB `_ is down. *An error occurred when downloading.* Donwloading the PDF didn't worked, please try again. From 00c95f48a9c0cce93e11ca1fa68501f9a2b8de1b Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 15 May 2025 11:40:51 +0200 Subject: [PATCH 58/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 4e8cc888..b6b5200c 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -9,7 +9,7 @@ sarah's note: search for TODO for all missing and needing of correction areas SciHubator ============== -.. image:: figures/TODO.png +.. image:: https://github.com/sarahperettipoix/orange3-textable-prototypes/blob/master/orangecontrib/textable_prototypes/widgets/icons/scihubator.png Download pdf files from `Sci-HUB `_ and extract textual content into segmentations From 445f701db08477e184177cd83f313f70c6bd4edf Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Thu, 15 May 2025 11:41:10 +0200 Subject: [PATCH 59/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index b6b5200c..f77ee9bc 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -1,5 +1,3 @@ -sarah's note: search for TODO for all missing and needing of correction areas - .. meta:: :description: Orange3 Textable Prototypes documentation, SciHubator widget :keywords: Orange3, Textable, Prototypes, documentation, SciHubator, widget From af53c6d713c96d6075e18f0b84aa425bac199213 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 15 May 2025 12:01:36 +0200 Subject: [PATCH 60/86] sa march tkt --- .../widgets/SciHubatorTest.py | 83 ++++++++++++------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 9e498fbc..fac64223 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -25,6 +25,7 @@ __maintainer__ = "Aris Xanthos" __email__ = "aris.xanthos@unil.ch" +import re # Standard imports... import time import tempfile @@ -39,6 +40,7 @@ OWTextableBaseWidget, VersionedSettingsHandler, ProgressBar, InfoBox, SendButton, pluralize, Task ) +from LTTL.Segmenter import tokenize from LTTL.Segmentation import Segmentation from Orange.widgets import widget, gui, settings from Orange.widgets.utils.widgetpreview import WidgetPreview @@ -250,7 +252,7 @@ def __init__(self): widget=advOptionsBox, master=self, value='importAll', - label=u'All', + label=u'All in one Segment', labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( @@ -431,21 +433,57 @@ def processData(self): label = self.captionTitle else: label = None # will be set later. + myInput = Input(DOIText, label) - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment + self.signal_text.emit("Step 3/3: Post-processing...", + "warning") + cur_itr = 0 + self.signal_prog.emit(0, True) + max_itr = int(self.importAll) + int(self.importText) + int(self.importBibliography) - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput) + if self.importText: + cur_itr += 1 + ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') + regexes = [(ma_regex,'tokenize')] + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + new_segmentation = tokenize(myInput, regexes) + print("*" * 100) + print(len(new_segmentation)) + print(new_segmentation.to_string()) + if(len(new_segmentation) == 0): + new_segmentation = Segmentation(Segment()) + new_segmentation[0].annotations["part"] = "Top level sections" + self.createdInputs.append(new_segmentation) + + if self.importBibliography: + cur_itr += 1 + ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') + regexes = [(ma_regex, 'tokenize')] + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + new_segmentation = tokenize(myInput, regexes) + print("#"*100) + print(new_segmentation.to_string()) + new_segmentation[0].annotations["part"] = "Bibliography" + self.createdInputs.append(new_segmentation) + + if self.importAbstract: + cur_itr += 1 + myInput = Input(DOIText, label) + + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. + segment = myInput[0] + segment.annotations["DOI"] \ + = DOI + # For the annotation to be saved in the LTTL.Input, + # the extracted and annotated segment must be re-assigned + # to the first (and only) segment of the LTTL.Input. + myInput[0] = segment + + # Add the LTTL.Input to self.createdInputs. + self.createdInputs.append(myInput) # Cancel operation if requested by user... time.sleep(0.00001) # Needed somehow! @@ -454,25 +492,6 @@ def processData(self): return tempdir.cleanup() - #Ajouter les regex - - if not self.importAll and (self.importAbstract or self.importText or self.importBibliography): - self.signal_text.emit("Step 3/3: Post-processing...", - "warning") - cur_itr = 0 - self.signal_prog.emit(0, True) - max_itr = int(self.importAll) + int(self.importText) + int(self.importBibliography) + int(self.importAbstract) - - if self.importAbstract: - regexes = [(r'/(Abstract.+?\n{1,})((.|\n)*)(?=\n\n)/gmi', "tokenize")] - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - - if self.importText: - regex = r'???' - - if self.importBibliography: - regex = r'#/(?<=\n)\n((biblio|r(e|é)f)\w*\W*\n)(.|\n)*/' From 14fd590cfc2719fe39bc4fd7ef5afe642c569bf6 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 15 May 2025 14:19:13 +0200 Subject: [PATCH 61/86] abstract mis en commentaire --- .../textable_prototypes/widgets/SciHubatorTest.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index fac64223..13938a46 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -135,7 +135,7 @@ class SciHubator(OWTextableBaseWidget): # Ici-dessous les variables qui n'ont pas été copiées, et conçues spécialement pour SciHubator importAll = Setting(True) - importAbstract = Setting(False) + """importAbstract = Setting(False)""" importText = Setting(False) importBibliography = Setting(False) @@ -259,7 +259,7 @@ def __init__(self): u"Import DOIs as annotations." ), ) - gui.separator(widget=advOptionsBox, height=3) + """gui.separator(widget=advOptionsBox, height=3) gui.checkBox( widget=advOptionsBox, master=self, @@ -270,7 +270,7 @@ def __init__(self): tooltip=( u"Import DOIs as annotations." ), - ) + )""" gui.separator(widget=advOptionsBox, height=3) gui.checkBox( widget=advOptionsBox, @@ -467,7 +467,7 @@ def processData(self): new_segmentation[0].annotations["part"] = "Bibliography" self.createdInputs.append(new_segmentation) - if self.importAbstract: + """if self.importAbstract: cur_itr += 1 myInput = Input(DOIText, label) @@ -483,7 +483,7 @@ def processData(self): myInput[0] = segment # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput) + self.createdInputs.append(myInput)""" # Cancel operation if requested by user... time.sleep(0.00001) # Needed somehow! @@ -492,7 +492,7 @@ def processData(self): return tempdir.cleanup() - + # If there's only one LTTL.Input created, it is the From 790609a759f7597a8d1156a288e09560701b2014 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 15 May 2025 14:27:43 +0200 Subject: [PATCH 62/86] all should work i guess --- .../widgets/SciHubatorTest.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 13938a46..ec00cbe9 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -441,7 +441,21 @@ def processData(self): cur_itr = 0 self.signal_prog.emit(0, True) max_itr = int(self.importAll) + int(self.importText) + int(self.importBibliography) - + if self.importAll: + cur_itr += 1 + myInput = Input(DOIText, label) + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. + segment = myInput[0] + segment.annotations["DOI"] \ + = DOI + # For the annotation to be saved in the LTTL.Input, + # the extracted and annotated segment must be re-assigned + # to the first (and only) segment of the LTTL.Input. + myInput[0] = segment + # Add the LTTL.Input to self.createdInputs. + self.createdInputs.append(myInput) if self.importText: cur_itr += 1 ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') @@ -455,7 +469,6 @@ def processData(self): new_segmentation = Segmentation(Segment()) new_segmentation[0].annotations["part"] = "Top level sections" self.createdInputs.append(new_segmentation) - if self.importBibliography: cur_itr += 1 ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') From 8533bb564ddd0852363d07cc8622ba9a158beff6 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 15 May 2025 15:19:11 +0200 Subject: [PATCH 63/86] les larmes --- .../widgets/SciHubatorTest.py | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index ec00cbe9..65ba8090 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -319,6 +319,11 @@ def sendData(self): before calling the method that does the actual processing. """ + # Verify checkboxes + if not (self.importAll or self.importBibliography or self.importText): + self.infoBox.setText("Please select one or more checkboxes.", "warning") + self.send("Segmentation", None) + return # Verify DOIs if not self.DOIs: self.infoBox.setText("Please enter one or many valid DOIs.", "warning") @@ -406,6 +411,7 @@ def processData(self): "warning") cur_itr = 0 self.signal_prog.emit(0, True) + empty_re = False for DOI in self.DOIs: DOIText = "" if os.path.exists(f"{tempdir.name}/{self.DOIs.index(DOI)}.pdf"): @@ -442,8 +448,8 @@ def processData(self): self.signal_prog.emit(0, True) max_itr = int(self.importAll) + int(self.importText) + int(self.importBibliography) if self.importAll: + cur_itr += 1 - myInput = Input(DOIText, label) # Extract the first (and single) segment in the # newly created LTTL.Input and annotate it with # the length of the input segmentation. @@ -466,10 +472,15 @@ def processData(self): print(len(new_segmentation)) print(new_segmentation.to_string()) if(len(new_segmentation) == 0): - new_segmentation = Segmentation(Segment()) - new_segmentation[0].annotations["part"] = "Top level sections" - self.createdInputs.append(new_segmentation) - if self.importBibliography: + print("cucou") + empty_re = True + new_input = Input("","Empty Top level sections") + else: + new_segmentation[0].annotations["DOI"] = "Top level sections" + new_input = Input(new_segmentation.to_string(), "") + new_input[0]= new_segmentation[0] + self.createdInputs.append(new_input) + if self.importBibliography: cur_itr += 1 ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') regexes = [(ma_regex, 'tokenize')] @@ -477,6 +488,9 @@ def processData(self): new_segmentation = tokenize(myInput, regexes) print("#"*100) print(new_segmentation.to_string()) + if (len(new_segmentation) == 0): + empty_re = True + new_segmentation = Input("", "Empty Bibliography section") new_segmentation[0].annotations["part"] = "Bibliography" self.createdInputs.append(new_segmentation) @@ -510,9 +524,14 @@ def processData(self): # If there's only one LTTL.Input created, it is the # widget's output... + print(empty_re) + if empty_re: + QMessageBox.warning( + None, "SciHubator", "Not all sections were segmented", + QMessageBox.Ok + ) if len(self.DOIs) == 1: return self.createdInputs[0] - # Otherwise the widget's output is a concatenation... else: return Segmenter.concatenate( From ac98506068f8b45eb5bde4c5b4ff9f57b4867c8e Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Fri, 16 May 2025 13:53:52 +0200 Subject: [PATCH 64/86] enlever les abstract sections --- .../widgets/SciHubatorTest.py | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 65ba8090..31a6c7aa 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -135,7 +135,6 @@ class SciHubator(OWTextableBaseWidget): # Ici-dessous les variables qui n'ont pas été copiées, et conçues spécialement pour SciHubator importAll = Setting(True) - """importAbstract = Setting(False)""" importText = Setting(False) importBibliography = Setting(False) @@ -259,18 +258,6 @@ def __init__(self): u"Import DOIs as annotations." ), ) - """gui.separator(widget=advOptionsBox, height=3) - gui.checkBox( - widget=advOptionsBox, - master=self, - value='importAbstract', - label=u'Abstract', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"Import DOIs as annotations." - ), - )""" gui.separator(widget=advOptionsBox, height=3) gui.checkBox( widget=advOptionsBox, @@ -494,24 +481,6 @@ def processData(self): new_segmentation[0].annotations["part"] = "Bibliography" self.createdInputs.append(new_segmentation) - """if self.importAbstract: - cur_itr += 1 - myInput = Input(DOIText, label) - - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment - - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput)""" - # Cancel operation if requested by user... time.sleep(0.00001) # Needed somehow! if self.cancel_operation: @@ -554,12 +523,6 @@ def task_finished(self, f): if processed_data: message = "Text sent to output " message = pluralize(message, len(processed_data)) - """numChars = 0 - for segment in processed_data: - segmentLength = len(Segmentation.get_data(segment.str_index)) - numChars += segmentLength - message += f"({numChars} character@p)." - message = pluralize(message, numChars)""" self.infoBox.setText(message) self.send("Segmentation", processed_data) From e8b8a61dfaedb7783e637d7e942d0de3d536a099 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Mon, 19 May 2025 08:58:27 +0200 Subject: [PATCH 65/86] changer image et enlever commentaires --- .../widgets/SciHubatorTest.py | 138 +----------------- 1 file changed, 1 insertion(+), 137 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 31a6c7aa..13f8256a 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -106,7 +106,7 @@ class SciHubator(OWTextableBaseWidget): name = "Sci-Hubator" description = "Export a text segmentation from a DOI or URL" - icon = "icons/lexical_hunter.svg" + icon = "icons/scihubator.png" priority = 10 # ---------------------------------------------------------------------- @@ -579,36 +579,6 @@ def add(self): self.clearAllButton.setDisabled(not bool(self.DOIs)) self.sendButton.settingsChanged() - # def updateGUI(self): - # """Update GUI state""" - # # if self.selectedURLLabel: - # # cachedLabel = self.selectedURLLabel[0] - # # else: - # # cachedLabel = None - # del self.URLLabel[:] - # if self.DOIs: - # DOIs = [f for f in self.DOIs] - # self.URLLabel = DOIs - # # maxURLLen = max([len(n) for n in DOIs]) - # # for DOI in DOIs: #range(len(self.DOIs)): - # # format = u'%-' + str(maxURLLen + 2) + u's' - # #format % DOIs[index] - # # self.URLLabel.append(DOI) - # self.URLLabel = self.URLLabel - # # if cachedLabel is not None: - # # self.sendButton.sendIfPreCallback = None - # # self.selectedURLLabel = [cachedLabel] - # # self.sendButton.sendIfPreCallback = self.updateGUI - # if self.newDOI: - # self.addButton.setDisabled(False) - # else: - # self.addButton.setDisabled(True) - # # if self.importDOIs: - # # self.importDOIsKeyLineEdit.setDisabled(False) - # # else: - # # self.importDOIsKeyLineEdit.setDisabled(True) - # self.updateURLBoxButtons() - def updateURLBoxButtons(self): """Update state of File box buttons""" self.addButton.setDisabled(not bool(self.newDOI)) @@ -637,109 +607,3 @@ def test_scihub_accessible(): if __name__ == '__main__': WidgetPreview(SciHubator).run() - - - # def clearAll(self): - # """Remove all DOIs from DOIs attr""" - # del self.DOIs[:] - # del self.selectedURLLabel[:] - # self.sendButton.settingsChanged() - - # def remove(self): - # """Remove URL from DOIs attr""" - # if self.selectedURLLabel: - # index = self.selectedURLLabel[0] - # self.DOIs.pop(index) - # del self.selectedURLLabel[:] - # self.sendButton.settingsChanged() - - # def add(self): - # """Add DOIs to DOIs attr""" - # URLList = re.split(r' +/ +', self.newURL) - # for URL in URLList: - # encoding = re.sub(r"[ ]\(.+", "", self.encoding) - # self.DOIs.append(( - # URL, - # encoding, - # self.newAnnotationKey, - # self.newAnnotationValue, - # )) - # self.sendButton.settingsChanged() - # def updateGUI(self): - # """Update GUI state""" - # if self.displayAdvancedSettings: - # if self.selectedURLLabel: - # cachedLabel = self.selectedURLLabel[0] - # else: - # cachedLabel = None - # del self.URLLabel[:] - # if self.DOIs: - # DOIs = [f[0] for f in self.DOIs] - # encodings = [f[1] for f in self.DOIs] - # annotations = ['{%s: %s}' % (f[2], f[3]) for f in self.DOIs] - # maxURLLen = max([len(n) for n in DOIs]) - # maxAnnoLen = max([len(a) for a in annotations]) - # for index in range(len(self.DOIs)): - # format = u'%-' + str(maxURLLen + 2) + u's' - # URLLabel = format % DOIs[index] - # if maxAnnoLen > 4: - # if len(annotations[index]) > 4: - # format = u'%-' + str(maxAnnoLen + 2) + u's' - # URLLabel += format % annotations[index] - # else: - # URLLabel += u' ' * (maxAnnoLen + 2) - # URLLabel += encodings[index] - # self.URLLabel.append(URLLabel) - # self.URLLabel = self.URLLabel - # if cachedLabel is not None: - # self.sendButton.sendIfPreCallback = None - # self.selectedURLLabel = [cachedLabel] - # self.sendButton.sendIfPreCallback = self.updateGUI - # if self.newURL: - # if ( - # (self.newAnnotationKey and self.newAnnotationValue) or - # (not self.newAnnotationKey and not self.newAnnotationValue) - # ): - # self.addButton.setDisabled(False) - # else: - # self.addButton.setDisabled(True) - # else: - # self.addButton.setDisabled(True) - # if self.autoNumber: - # self.autoNumberKeyLineEdit.setDisabled(False) - # else: - # self.autoNumberKeyLineEdit.setDisabled(True) - # if self.importDOIs: - # self.importDOIsKeyLineEdit.setDisabled(False) - # else: - # self.importDOIsKeyLineEdit.setDisabled(True) - # self.updateURLBoxButtons() - # self.advancedSettings.setVisible(True) - # else: - # self.advancedSettings.setVisible(False) - - # def updateURLBoxButtons(self): - # """Update state of File box buttons""" - # if self.selectedURLLabel: - # self.removeButton.setDisabled(False) - # if self.selectedURLLabel[0] > 0: - # self.moveUpButton.setDisabled(False) - # else: - # self.moveUpButton.setDisabled(True) - # if self.selectedURLLabel[0] < len(self.DOIs) - 1: - # self.moveDownButton.setDisabled(False) - # else: - # self.moveDownButton.setDisabled(True) - # else: - # self.moveUpButton.setDisabled(True) - # self.moveDownButton.setDisabled(True) - # self.removeButton.setDisabled(True) - # if len(self.DOIs): - # self.clearAllButton.setDisabled(False) - # self.exportButton.setDisabled(False) - # else: - # self.clearAllButton.setDisabled(True) - # self.exportButton.setDisabled(True) - -# def checkIfDOI(string): -# regex = re.compile(r'\d{2}\.\d{4}.+') \ No newline at end of file From 8a7c487622ec0403508a0e5e9b36310524bbb2f0 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Mon, 19 May 2025 09:20:19 +0200 Subject: [PATCH 66/86] correction --- doc/widgets/SciHubator.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index f77ee9bc..56526547 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -78,7 +78,7 @@ Advanced interface ~~~~~~~~~~~~~~~~~~ The advanced version of **SciHubator** allows the user to type several DOIs -in a determined order; each outputed text file can moreover be segmented into +in a determined order; each output text file can moreover be segmented into specific segmentations (introduction, mais corpus and bibliography) with specific annotations. The emitted segmentation contains a segment for each imported file. @@ -161,13 +161,13 @@ Errors ~~~~~~ *SciHub inaccessible - verify your connexion.* - Plese verify your internet connexion or check if `Sci-HUB `_ is down. + Please verify your internet connexion or check if `Sci-HUB `_ is down. *An error occurred when downloading.* - Donwloading the PDF didn't worked, please try again. + Downloading the PDF didn't worked, please try again. *Error occurred when reading PDF:* - An unexpected error occured when reading the downloaded PDF. Please try again, if the error still happen your DOI could be not compatible. + An unexpected error occurred when reading the downloaded PDF. Please try again, if the error still happen your DOI could be not compatible. *Download failed. Please, verify DOI or connexion.* Sci-Hub is accessible but scihubator couldn't download the PDF. Your connexion has perhaps crashed in the download process or the DOI provided is not valid. From fed37da0e61d2a74d66f44a81ea468218b9daddd Mon Sep 17 00:00:00 2001 From: ColinLug Date: Mon, 19 May 2025 09:39:08 +0200 Subject: [PATCH 67/86] =?UTF-8?q?les=20larmes=20ont=20cess=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/SciHubatorTest.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 65ba8090..46e7ae5c 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -136,7 +136,7 @@ class SciHubator(OWTextableBaseWidget): # Ici-dessous les variables qui n'ont pas été copiées, et conçues spécialement pour SciHubator importAll = Setting(True) """importAbstract = Setting(False)""" - importText = Setting(False) + """importText = Setting(False)""" importBibliography = Setting(False) def __init__(self): @@ -271,7 +271,7 @@ def __init__(self): u"Import DOIs as annotations." ), )""" - gui.separator(widget=advOptionsBox, height=3) + """gui.separator(widget=advOptionsBox, height=3) gui.checkBox( widget=advOptionsBox, master=self, @@ -282,7 +282,7 @@ def __init__(self): tooltip=( u"Import DOIs as annotations." ), - ) + )""" gui.separator(widget=advOptionsBox, height=3) gui.checkBox( widget=advOptionsBox, @@ -320,7 +320,7 @@ def sendData(self): processing. """ # Verify checkboxes - if not (self.importAll or self.importBibliography or self.importText): + if not (self.importAll or self.importBibliography): #or self.importText self.infoBox.setText("Please select one or more checkboxes.", "warning") self.send("Segmentation", None) return @@ -446,7 +446,7 @@ def processData(self): "warning") cur_itr = 0 self.signal_prog.emit(0, True) - max_itr = int(self.importAll) + int(self.importText) + int(self.importBibliography) + max_itr = int(self.importAll) + int(self.importBibliography) #+ int(self.importText) if self.importAll: cur_itr += 1 @@ -462,7 +462,7 @@ def processData(self): myInput[0] = segment # Add the LTTL.Input to self.createdInputs. self.createdInputs.append(myInput) - if self.importText: + """if self.importText: cur_itr += 1 ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') regexes = [(ma_regex,'tokenize')] @@ -479,20 +479,22 @@ def processData(self): new_segmentation[0].annotations["DOI"] = "Top level sections" new_input = Input(new_segmentation.to_string(), "") new_input[0]= new_segmentation[0] - self.createdInputs.append(new_input) + self.createdInputs.append(new_segmentation)""" if self.importBibliography: cur_itr += 1 ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') regexes = [(ma_regex, 'tokenize')] self.signal_prog.emit(int(100 * cur_itr / max_itr), False) new_segmentation = tokenize(myInput, regexes) - print("#"*100) - print(new_segmentation.to_string()) if (len(new_segmentation) == 0): empty_re = True - new_segmentation = Input("", "Empty Bibliography section") - new_segmentation[0].annotations["part"] = "Bibliography" - self.createdInputs.append(new_segmentation) + new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") + else: + new_segmentation[0].annotations["part"] = "Bibliography" + new_input = Input(new_segmentation.to_string(), "Bibliographies") + new_input[0].annotations["part"] = "Bibliography" + new_input[0] = new_segmentation[0] + self.createdInputs.append(new_input) """if self.importAbstract: cur_itr += 1 From 23aa031b11e825f9589148bdbb83182170abd8e5 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Mon, 19 May 2025 09:44:43 +0200 Subject: [PATCH 68/86] corrections --- .../widgets/SciHubatorTest.py | 231 ++---------------- 1 file changed, 19 insertions(+), 212 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 46e7ae5c..837bedbe 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -37,12 +37,12 @@ from functools import partial from scidownl import scihub_download from _textable.widgets.TextableUtils import ( - OWTextableBaseWidget, VersionedSettingsHandler, ProgressBar, - InfoBox, SendButton, pluralize, Task + OWTextableBaseWidget, + InfoBox, SendButton, pluralize ) from LTTL.Segmenter import tokenize from LTTL.Segmentation import Segmentation -from Orange.widgets import widget, gui, settings +from Orange.widgets import gui, settings from Orange.widgets.utils.widgetpreview import WidgetPreview from LTTL.Input import Input from Orange.widgets.settings import Setting @@ -52,61 +52,13 @@ class SciHubator(OWTextableBaseWidget): """An Orange widget that lets the user select an integer value""" #Version minimale - """ - basicURLBox = gui.widgetBox( - widget=self.controlArea, - box=u'Source', - orientation='vertical', - addSpace=False, - ) - basicURLBoxLine1 = gui.widgetBox( - widget=basicURLBox, - box=False, - orientation='horizontal', - ) - gui.lineEdit( - widget=basicURLBoxLine1, - master=self, - value='URL', - orientation='horizontal', - label=u'DOI:', - labelWidth=101, - callback=self.sendButton.settingsChanged, - tooltip=( - u"The URL whose content will be imported." - ), - ) - gui.rubber(self.controlArea) - - self.exportButton = gui.button( - widget=URLBoxCol2, - master=self, - label=u'Export List', - callback=self.exportList, - tooltip=( - u"Open a dialog for selecting a file where the URL\n" - u"list can be exported in JSON format." - ), - ) - self.importButton = gui.button( - widget=URLBoxCol2, - master=self, - label=u'Import List', - callback=self.importList, - tooltip=( - u"Open a dialog for selecting an URL list to\n" - u"import (in JSON format). DOIs from this list will\n" - u"be added to those already imported." - ), - ) - """ # ---------------------------------------------------------------------- # Widget's metadata... name = "Sci-Hubator" description = "Export a text segmentation from a DOI or URL" - icon = "icons/lexical_hunter.svg" + icon = "icons/scihubator.svg" priority = 10 # ---------------------------------------------------------------------- @@ -462,6 +414,21 @@ def processData(self): myInput[0] = segment # Add the LTTL.Input to self.createdInputs. self.createdInputs.append(myInput) + if self.importBibliography: + cur_itr += 1 + ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') + regexes = [(ma_regex, 'tokenize')] + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + new_segmentation = tokenize(myInput, regexes) + if (len(new_segmentation) == 0): + empty_re = True + new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") + else: + new_segmentation[0].annotations["part"] = "Bibliography" + new_input = Input(new_segmentation.to_string(), "Bibliographies") + new_input[0].annotations["part"] = "Bibliography" + new_input[0] = new_segmentation[0] + self.createdInputs.append(new_input) """if self.importText: cur_itr += 1 ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') @@ -480,22 +447,6 @@ def processData(self): new_input = Input(new_segmentation.to_string(), "") new_input[0]= new_segmentation[0] self.createdInputs.append(new_segmentation)""" - if self.importBibliography: - cur_itr += 1 - ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') - regexes = [(ma_regex, 'tokenize')] - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - if (len(new_segmentation) == 0): - empty_re = True - new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") - else: - new_segmentation[0].annotations["part"] = "Bibliography" - new_input = Input(new_segmentation.to_string(), "Bibliographies") - new_input[0].annotations["part"] = "Bibliography" - new_input[0] = new_segmentation[0] - self.createdInputs.append(new_input) - """if self.importAbstract: cur_itr += 1 myInput = Input(DOIText, label) @@ -520,8 +471,6 @@ def processData(self): self.signal_prog.emit(100, False) return tempdir.cleanup() - - # If there's only one LTTL.Input created, it is the @@ -556,12 +505,6 @@ def task_finished(self, f): if processed_data: message = "Text sent to output " message = pluralize(message, len(processed_data)) - """numChars = 0 - for segment in processed_data: - segmentLength = len(Segmentation.get_data(segment.str_index)) - numChars += segmentLength - message += f"({numChars} character@p)." - message = pluralize(message, numChars)""" self.infoBox.setText(message) self.send("Segmentation", processed_data) @@ -618,36 +561,6 @@ def add(self): self.clearAllButton.setDisabled(not bool(self.DOIs)) self.sendButton.settingsChanged() - # def updateGUI(self): - # """Update GUI state""" - # # if self.selectedURLLabel: - # # cachedLabel = self.selectedURLLabel[0] - # # else: - # # cachedLabel = None - # del self.URLLabel[:] - # if self.DOIs: - # DOIs = [f for f in self.DOIs] - # self.URLLabel = DOIs - # # maxURLLen = max([len(n) for n in DOIs]) - # # for DOI in DOIs: #range(len(self.DOIs)): - # # format = u'%-' + str(maxURLLen + 2) + u's' - # #format % DOIs[index] - # # self.URLLabel.append(DOI) - # self.URLLabel = self.URLLabel - # # if cachedLabel is not None: - # # self.sendButton.sendIfPreCallback = None - # # self.selectedURLLabel = [cachedLabel] - # # self.sendButton.sendIfPreCallback = self.updateGUI - # if self.newDOI: - # self.addButton.setDisabled(False) - # else: - # self.addButton.setDisabled(True) - # # if self.importDOIs: - # # self.importDOIsKeyLineEdit.setDisabled(False) - # # else: - # # self.importDOIsKeyLineEdit.setDisabled(True) - # self.updateURLBoxButtons() - def updateURLBoxButtons(self): """Update state of File box buttons""" self.addButton.setDisabled(not bool(self.newDOI)) @@ -676,109 +589,3 @@ def test_scihub_accessible(): if __name__ == '__main__': WidgetPreview(SciHubator).run() - - - # def clearAll(self): - # """Remove all DOIs from DOIs attr""" - # del self.DOIs[:] - # del self.selectedURLLabel[:] - # self.sendButton.settingsChanged() - - # def remove(self): - # """Remove URL from DOIs attr""" - # if self.selectedURLLabel: - # index = self.selectedURLLabel[0] - # self.DOIs.pop(index) - # del self.selectedURLLabel[:] - # self.sendButton.settingsChanged() - - # def add(self): - # """Add DOIs to DOIs attr""" - # URLList = re.split(r' +/ +', self.newURL) - # for URL in URLList: - # encoding = re.sub(r"[ ]\(.+", "", self.encoding) - # self.DOIs.append(( - # URL, - # encoding, - # self.newAnnotationKey, - # self.newAnnotationValue, - # )) - # self.sendButton.settingsChanged() - # def updateGUI(self): - # """Update GUI state""" - # if self.displayAdvancedSettings: - # if self.selectedURLLabel: - # cachedLabel = self.selectedURLLabel[0] - # else: - # cachedLabel = None - # del self.URLLabel[:] - # if self.DOIs: - # DOIs = [f[0] for f in self.DOIs] - # encodings = [f[1] for f in self.DOIs] - # annotations = ['{%s: %s}' % (f[2], f[3]) for f in self.DOIs] - # maxURLLen = max([len(n) for n in DOIs]) - # maxAnnoLen = max([len(a) for a in annotations]) - # for index in range(len(self.DOIs)): - # format = u'%-' + str(maxURLLen + 2) + u's' - # URLLabel = format % DOIs[index] - # if maxAnnoLen > 4: - # if len(annotations[index]) > 4: - # format = u'%-' + str(maxAnnoLen + 2) + u's' - # URLLabel += format % annotations[index] - # else: - # URLLabel += u' ' * (maxAnnoLen + 2) - # URLLabel += encodings[index] - # self.URLLabel.append(URLLabel) - # self.URLLabel = self.URLLabel - # if cachedLabel is not None: - # self.sendButton.sendIfPreCallback = None - # self.selectedURLLabel = [cachedLabel] - # self.sendButton.sendIfPreCallback = self.updateGUI - # if self.newURL: - # if ( - # (self.newAnnotationKey and self.newAnnotationValue) or - # (not self.newAnnotationKey and not self.newAnnotationValue) - # ): - # self.addButton.setDisabled(False) - # else: - # self.addButton.setDisabled(True) - # else: - # self.addButton.setDisabled(True) - # if self.autoNumber: - # self.autoNumberKeyLineEdit.setDisabled(False) - # else: - # self.autoNumberKeyLineEdit.setDisabled(True) - # if self.importDOIs: - # self.importDOIsKeyLineEdit.setDisabled(False) - # else: - # self.importDOIsKeyLineEdit.setDisabled(True) - # self.updateURLBoxButtons() - # self.advancedSettings.setVisible(True) - # else: - # self.advancedSettings.setVisible(False) - - # def updateURLBoxButtons(self): - # """Update state of File box buttons""" - # if self.selectedURLLabel: - # self.removeButton.setDisabled(False) - # if self.selectedURLLabel[0] > 0: - # self.moveUpButton.setDisabled(False) - # else: - # self.moveUpButton.setDisabled(True) - # if self.selectedURLLabel[0] < len(self.DOIs) - 1: - # self.moveDownButton.setDisabled(False) - # else: - # self.moveDownButton.setDisabled(True) - # else: - # self.moveUpButton.setDisabled(True) - # self.moveDownButton.setDisabled(True) - # self.removeButton.setDisabled(True) - # if len(self.DOIs): - # self.clearAllButton.setDisabled(False) - # self.exportButton.setDisabled(False) - # else: - # self.clearAllButton.setDisabled(True) - # self.exportButton.setDisabled(True) - -# def checkIfDOI(string): -# regex = re.compile(r'\d{2}\.\d{4}.+') \ No newline at end of file From f94ab87c3378e34de625d8920bcd369017612e59 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Mon, 19 May 2025 09:48:51 +0200 Subject: [PATCH 69/86] update image v. maximale --- specs/images/scihubator_principal.png | Bin 31083 -> 33551 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/specs/images/scihubator_principal.png b/specs/images/scihubator_principal.png index 819a38e75ec16e98f894ca22fbaa6e68e33dc28d..f3b3e84e570d0fefbe9cb2c0f5878cb439a93742 100644 GIT binary patch literal 33551 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 JnTX!+{{dQ5ePI9q literal 31083 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 From 1f2148fa33c7d7c50c7f07a4b322ccda3de41ade Mon Sep 17 00:00:00 2001 From: ColinLug Date: Mon, 19 May 2025 09:49:56 +0200 Subject: [PATCH 70/86] update nom spec --- specs/SCi-Hubator.rst | 116 ------------------------------------------ 1 file changed, 116 deletions(-) delete mode 100644 specs/SCi-Hubator.rst diff --git a/specs/SCi-Hubator.rst b/specs/SCi-Hubator.rst deleted file mode 100644 index 222ce3c0..00000000 --- a/specs/SCi-Hubator.rst +++ /dev/null @@ -1,116 +0,0 @@ -############################ -Specification widget SCI-HUbator -############################ - -1 Introduction -************** - -1.1 But du projet -================= -Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'extraction de corpus tirés de `Sci-HUB `_ - -1.2 Aperçu des étapes -===================== -* Première version des spécifications: 13.03.2025 -* Remise des spécifications: 20.03.2025 -* Version alpha du projet: 17.04.2025 -* Version finale du projet: 22.05.2025 - -1.3 Equipe et résponsabilités -============================== - -* Luginbühl Colin (`colin.luginbuhl@unil.ch`_): - -.. _colin.luginbuhl@unil.ch: mailto:colin.luginbuhl@unil.ch - - - Specification - - Extraction des données - - Code - - Documentation - -* Borgeaud Matthias (`matthias.borgeaud@unil.ch`_): - -.. _matthias.borgeaud@unil.ch: mailto:matthias.borgeaud@unil.ch - - - Spécification - - Code - - Documentation - - Vérification orthographe - -* Peretti-Poix Sarah (`sarah.peretti-poix@unil.ch`_): - -.. _sarah.peretti-poix@unil.ch: mailto:sarah.peretti-poix@unil.ch - - - Spécification - - GitHub - - Code - - Débuggage - -* Chétioui Orsowen (`orsowen.chetioui@unil.ch`_): - -.. _orsowen.chetioui@unil.ch: mailto:orsowen.chetioui@unil.ch - - - Documentation - - Code - - Débuggage - -2. Technique -************ - -2.1 Dépendances -=============== -* Orange 3.38.1 -* Orange Textable 3.2.2 -* `scidownl `_ 1.0.2 -* `pdfplumber `_ 0.11.6 (déjà présent pour SuperTextFiles) - - -2.2 Fonctionnalités minimales -============================= - -.. image:: images/scihubator_minimal.png - -* permettre l'importation de pdf tirés de SCI-HUB à l'aide d'un DOI et l'extraction du corpus textuel. -* créer et émettre une segmentation avec un segment (=Input) comprenant l'entièreté du texte du PDF. - -2.3 Fonctionnalités principales -=============================== - -.. image:: images/scihubator_principal.png - -* permettre l'importation de pdf tirés de SCI-HUB (à partir d'un DOI). -* permettre d'en tirer le texte. -* permettre la constitution d'une sélection de corpus multiples (add/remove/clear). -* créer et émettre une segmentation avec un segment (=Input) pour chaque partie du corpus importé (résumé/abstract, bibliographie...). -* traitement correct des références - -2.4 Fonctionnalités optionnelles -================================ -* créer et émettre une segmentation par thème. -* créer et émettre un résumé/abstract. -* créer et émettre un tableau de cross-reference. -* importer un JSON contenant plusieurs DOI. - -2.5 Tests -========= - -TODO - -3. Etapes -********* - -3.1 Version alpha -================= -* L'interface graphique est complètement construite. -* Les fonctionnalités minimales sont prises en charge par le logiciel. - -3.2 Remise et présentation -========================== -* Les fonctionnalités principales sont complétement prises en charge par le logiciel. -* La documentation du logiciel est complète. - - -4. Infrastructure -================= -Le projet est disponible sur GitHub à l'adresse `https://github.com/sarahperettipoix/orange3-textable-prototypes -`_ From a17e35da07dfca499c443d7115893933c084443c Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Mon, 19 May 2025 09:50:19 +0200 Subject: [PATCH 71/86] png --- .../widgets/icons/scihubator.png | Bin 8655 -> 8577 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/icons/scihubator.png b/orangecontrib/textable_prototypes/widgets/icons/scihubator.png index d18166ac69d17c25b8a79096b803971c46800959..e91e916c758fe976a255f7ba9f785e76cb009b66 100644 GIT binary patch delta 7545 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 AR?oXj|eCR@rQ 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 Date: Mon, 19 May 2025 09:54:04 +0200 Subject: [PATCH 72/86] svg --- .../widgets/icons/scihubator.svg | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 orangecontrib/textable_prototypes/widgets/icons/scihubator.svg diff --git a/orangecontrib/textable_prototypes/widgets/icons/scihubator.svg b/orangecontrib/textable_prototypes/widgets/icons/scihubator.svg new file mode 100644 index 00000000..f141c9f3 --- /dev/null +++ b/orangecontrib/textable_prototypes/widgets/icons/scihubator.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + From 9735237975455ca9d97f142ad3ce62dfa72ceddd Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Wed, 21 May 2025 21:40:12 +0200 Subject: [PATCH 73/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 56526547..9602a8a5 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -63,7 +63,7 @@ The interface contains a **Source** section enabling the user to type the DOI. Figure 1: **SciHubator** widget (basic interface). Note that pdfplumber might not work properly with none latin alphabets -and serif typefaces. TODO +and serif typefaces. The **Send** button triggers the emission of a segmentation to the output connection(s). When it is selected, the **Send automatically** checkbox @@ -92,8 +92,7 @@ for each imported file. Figure 2: **SciHubator** widget (advanced interface). -The advanced interface (see :ref:`figure 2 ` -above) presents similarities with that of the **URLs** and **Segment** +The advanced interface presents similarities with that of the **URLs** and **Segment** widgets. The **Sources** section allows the user to select the input DOI(s). The list of imported files appears at the top of the window; the columns of this list From 31468397d336309d647553ecd205dd29f636b500 Mon Sep 17 00:00:00 2001 From: matBorgeaud <115068282+matBorgeaud@users.noreply.github.com> Date: Wed, 21 May 2025 21:40:43 +0200 Subject: [PATCH 74/86] Update SciHubator.rst --- doc/widgets/SciHubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index 9602a8a5..c880796d 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -50,7 +50,7 @@ into an annotated text segmentation. Basic interface ~~~~~~~~~~~~~~~ -In its basic version (see :ref:`figure 1 ` below), +In its basic version, the **SciHubator** widget is limited to the import of a single DOI. The interface contains a **Source** section enabling the user to type the DOI. From 976bf8450b77400a0430384bd0458e216d0589d9 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Wed, 21 May 2025 22:43:59 +0200 Subject: [PATCH 75/86] specs on line again --- specs/Sci-Hubator.rst | 116 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 specs/Sci-Hubator.rst diff --git a/specs/Sci-Hubator.rst b/specs/Sci-Hubator.rst new file mode 100644 index 00000000..222ce3c0 --- /dev/null +++ b/specs/Sci-Hubator.rst @@ -0,0 +1,116 @@ +############################ +Specification widget SCI-HUbator +############################ + +1 Introduction +************** + +1.1 But du projet +================= +Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'extraction de corpus tirés de `Sci-HUB `_ + +1.2 Aperçu des étapes +===================== +* Première version des spécifications: 13.03.2025 +* Remise des spécifications: 20.03.2025 +* Version alpha du projet: 17.04.2025 +* Version finale du projet: 22.05.2025 + +1.3 Equipe et résponsabilités +============================== + +* Luginbühl Colin (`colin.luginbuhl@unil.ch`_): + +.. _colin.luginbuhl@unil.ch: mailto:colin.luginbuhl@unil.ch + + - Specification + - Extraction des données + - Code + - Documentation + +* Borgeaud Matthias (`matthias.borgeaud@unil.ch`_): + +.. _matthias.borgeaud@unil.ch: mailto:matthias.borgeaud@unil.ch + + - Spécification + - Code + - Documentation + - Vérification orthographe + +* Peretti-Poix Sarah (`sarah.peretti-poix@unil.ch`_): + +.. _sarah.peretti-poix@unil.ch: mailto:sarah.peretti-poix@unil.ch + + - Spécification + - GitHub + - Code + - Débuggage + +* Chétioui Orsowen (`orsowen.chetioui@unil.ch`_): + +.. _orsowen.chetioui@unil.ch: mailto:orsowen.chetioui@unil.ch + + - Documentation + - Code + - Débuggage + +2. Technique +************ + +2.1 Dépendances +=============== +* Orange 3.38.1 +* Orange Textable 3.2.2 +* `scidownl `_ 1.0.2 +* `pdfplumber `_ 0.11.6 (déjà présent pour SuperTextFiles) + + +2.2 Fonctionnalités minimales +============================= + +.. image:: images/scihubator_minimal.png + +* permettre l'importation de pdf tirés de SCI-HUB à l'aide d'un DOI et l'extraction du corpus textuel. +* créer et émettre une segmentation avec un segment (=Input) comprenant l'entièreté du texte du PDF. + +2.3 Fonctionnalités principales +=============================== + +.. image:: images/scihubator_principal.png + +* permettre l'importation de pdf tirés de SCI-HUB (à partir d'un DOI). +* permettre d'en tirer le texte. +* permettre la constitution d'une sélection de corpus multiples (add/remove/clear). +* créer et émettre une segmentation avec un segment (=Input) pour chaque partie du corpus importé (résumé/abstract, bibliographie...). +* traitement correct des références + +2.4 Fonctionnalités optionnelles +================================ +* créer et émettre une segmentation par thème. +* créer et émettre un résumé/abstract. +* créer et émettre un tableau de cross-reference. +* importer un JSON contenant plusieurs DOI. + +2.5 Tests +========= + +TODO + +3. Etapes +********* + +3.1 Version alpha +================= +* L'interface graphique est complètement construite. +* Les fonctionnalités minimales sont prises en charge par le logiciel. + +3.2 Remise et présentation +========================== +* Les fonctionnalités principales sont complétement prises en charge par le logiciel. +* La documentation du logiciel est complète. + + +4. Infrastructure +================= +Le projet est disponible sur GitHub à l'adresse `https://github.com/sarahperettipoix/orange3-textable-prototypes +`_ From 73cfb857fb3f93e365df1f8aebf6e8bfe5b89eb9 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 22 May 2025 19:34:45 +0200 Subject: [PATCH 76/86] =?UTF-8?q?partie=201=20des=20corrections=20demand?= =?UTF-8?q?=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/widgets/SciHubator.rst | 20 +++++++++++-------- .../widgets/SciHubatorTest.py | 19 ++++++++---------- specs/Sci-Hubator.rst | 3 ++- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/doc/widgets/SciHubator.rst b/doc/widgets/SciHubator.rst index c880796d..f2ee005c 100644 --- a/doc/widgets/SciHubator.rst +++ b/doc/widgets/SciHubator.rst @@ -32,13 +32,8 @@ Requirements * Orange 3.38.1 * Orange Textable 3.2.2 -* from functools import partial -* import time * from scidownl import scihub_download -* import tempfile * import pdfplumber -* import os -* import requests Description ----------- @@ -130,9 +125,9 @@ Information button (or equivalently check the box) in order for computation and data emission to proceed. -*No data sent to output yet: no file selected.* +*No data sent to output yet: no DOI selected.* The widget instance is not able to emit data to output because no input - file has been selected. + DOI has been selected. *No data sent to output yet, see 'Widget state' below.* A problem with the instance's parameters and/or input data prevents it @@ -140,11 +135,20 @@ Information found in the **Widget state** box at the bottom of the instance's interface (see `Warnings`_ and `Errors`_ below). +*Duplicate DOI(s) found and deleted.* + A duplicate DOI was found in the DOI list. + Adding operation is halted so that no duplicates appear + + Warnings ~~~~~~~~ *Please enter one or many valid DOIs.* - A valid DOI is required for being processed by Sci-Hub. The warning indicates that nothing was typed in the DOI field. + A valid DOI is required for being processed by Sci-Hub. +The warning indicates that nothing was typed in the DOI field. + +*Not all sections were segmented* + The regex was not able to segment the content of certain DOIs. *Step 1/3: Pre-processing...* The PDF is being downloaded diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 837bedbe..cf67f8ca 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -136,10 +136,7 @@ def __init__(self): tooltip=( u"The list of DOIs whose content will be imported.\n" u"\nIn the output segmentation, the content of each\n" - u"URL appears in the same position as in the list.\n" - u"\nColumn 1 shows the URL.\n" - u"Column 2 shows the associated annotation (if any).\n" - u"Column 3 shows the associated encoding." + u"DOI appears in the same position as in the list.\n" ), ) URLBoxCol2 = gui.widgetBox( @@ -152,7 +149,7 @@ def __init__(self): label=u'Remove', callback=self.remove, tooltip=( - u"Remove the selected URL from the list." + u"Remove the selected DOI from the list." ), disabled = True, ) @@ -208,7 +205,7 @@ def __init__(self): labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( - u"Import DOIs as annotations." + u"Output entire text as a single segmentation." ), ) """gui.separator(widget=advOptionsBox, height=3) @@ -220,7 +217,7 @@ def __init__(self): labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( - u"Import DOIs as annotations." + u"Output Abstract as a segmentation." ), )""" """gui.separator(widget=advOptionsBox, height=3) @@ -232,7 +229,7 @@ def __init__(self): labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( - u"Import DOIs as annotations." + u"output main text as a segmentation." ), )""" gui.separator(widget=advOptionsBox, height=3) @@ -244,7 +241,7 @@ def __init__(self): labelWidth=180, callback=self.sendButton.settingsChanged, tooltip=( - u"Import DOIs as annotations." + u"output bibliography as a segmentation." ), ) gui.separator(widget=addURLBox, height=3) @@ -254,7 +251,7 @@ def __init__(self): label=u'Add', callback=self.add, tooltip=( - u"Add the URL currently displayed in the 'URL'\n" + u"Add the DOI currently displayed in the 'DOI'\n" u"text field to the list." ), disabled = True, @@ -503,7 +500,7 @@ def task_finished(self, f): # If it is not None... if processed_data: - message = "Text sent to output " + message = f"{len(processed_data)} segment@p sent to output " message = pluralize(message, len(processed_data)) self.infoBox.setText(message) self.send("Segmentation", processed_data) diff --git a/specs/Sci-Hubator.rst b/specs/Sci-Hubator.rst index 222ce3c0..3b73be41 100644 --- a/specs/Sci-Hubator.rst +++ b/specs/Sci-Hubator.rst @@ -81,7 +81,8 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext * permettre l'importation de pdf tirés de SCI-HUB (à partir d'un DOI). * permettre d'en tirer le texte. * permettre la constitution d'une sélection de corpus multiples (add/remove/clear). -* créer et émettre une segmentation avec un segment (=Input) pour chaque partie du corpus importé (résumé/abstract, bibliographie...). +* créer et émettre une segmentation avec un segment (=Input) +pour chaque partie du corpus importé (résumé/abstract, bibliographie...). * traitement correct des références 2.4 Fonctionnalités optionnelles From c434d98d6d73ad645ebe196581f4cee56f753a15 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Fri, 23 May 2025 00:43:21 +0200 Subject: [PATCH 77/86] =?UTF-8?q?orso=20doc=20ajout=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/SciHubatorTest.py | 464 +++++++++++------- 1 file changed, 276 insertions(+), 188 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 837bedbe..087fbfc7 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -42,14 +42,25 @@ ) from LTTL.Segmenter import tokenize from LTTL.Segmentation import Segmentation -from Orange.widgets import gui, settings +from Orange.widgets import widget, gui, settings from Orange.widgets.utils.widgetpreview import WidgetPreview from LTTL.Input import Input from Orange.widgets.settings import Setting from PyQt5.QtWidgets import QMessageBox class SciHubator(OWTextableBaseWidget): - """An Orange widget that lets the user select an integer value""" + """ + Orange widget for importing and segmenting text from DOIs using Sci-Hub. + + Attributes : + URLLabel (list) : List of labels for the DOIs. + selectedURLLabel (list) : List of selected labels from the URL list. + newDOI (str) : DOI entered by the user for addition. + extractedText (str) : Extracted text from the downladed PDF + DOI (str) : Single DOI value. + DOIs (list) : List of DOIs added by the user + createdInputs (list) : List of created LTTL.Inputs + """ #Version minimale @@ -86,12 +97,16 @@ class SciHubator(OWTextableBaseWidget): DOI = Setting(u'') # Ici-dessous les variables qui n'ont pas été copiées, et conçues spécialement pour SciHubator - importAll = Setting(True) + """importAll = Setting(True)""" """importAbstract = Setting(False)""" """importText = Setting(False)""" - importBibliography = Setting(False) + """importBibliography = Setting(False)""" + importAllorBib = Setting(0) def __init__(self): + """ + Initializes the SciHubator widget, including the GUI components and settings + """ super().__init__() self.URLLabel = self.DOIs[:] print(self.URLLabel) @@ -200,7 +215,7 @@ def __init__(self): orientation='vertical', addSpace=False, ) - gui.checkBox( + """gui.checkBox( widget=advOptionsBox, master=self, value='importAll', @@ -210,7 +225,7 @@ def __init__(self): tooltip=( u"Import DOIs as annotations." ), - ) + )""" """gui.separator(widget=advOptionsBox, height=3) gui.checkBox( widget=advOptionsBox, @@ -235,7 +250,7 @@ def __init__(self): u"Import DOIs as annotations." ), )""" - gui.separator(widget=advOptionsBox, height=3) + """gui.separator(widget=advOptionsBox, height=3) gui.checkBox( widget=advOptionsBox, master=self, @@ -246,6 +261,16 @@ def __init__(self): tooltip=( u"Import DOIs as annotations." ), + )""" + gui.separator(widget=advOptionsBox, height=3) + gui.radioButtonsInBox( + widget=advOptionsBox, + master=self, + value='importAllorBib', + btnLabels=['Bib', 'All'], + label=u'Bibliography', + callback=self.sendButton.settingsChanged, + tooltips=["Import all article's in one segment", "Import only bibliography (if found)"] ) gui.separator(widget=addURLBox, height=3) self.addButton = gui.button( @@ -267,9 +292,15 @@ def __init__(self): self.sendButton.sendIf() def sendData(self): - """Perform every required check and operation - before calling the method that does the actual - processing. + """ + Trigger the data processing workflow from user-provided DOIs. + + This method: + - Validates the presence of at least one DOI. + - Displays a warning if no DOI is provided. + - Clears any previously created inputs. + - Updates the UI to indicate the start of preprocessing. + - Launches the processing asynchronously using a background thread """ # Verify checkboxes if not (self.importAll or self.importBibliography): #or self.importText @@ -307,195 +338,224 @@ def sendData(self): self.threading(threaded_function) def processData(self): - """Actual processing takes place in this method, - which is run in a worker thread so that GUI stays - responsive and operations can be cancelled - """ - - # At start of processing, set progress bar to 1%. - # Within this method, this is done using the following - # instruction. - self.signal_prog.emit(1, False) - - # DOIList.append(self.DOIContent) - - # Indicate the total number of iterations that the - # progress bar will go through (e.g. number of input - # segments, number of selected files, etc.), then - # set current iteration to 1. - max_itr = len(self.DOIs) - cur_itr = 1 - - # Permet de tester la connexion à Sci-Hub - if not test_scihub_accessible(): - self.sendNoneToOutputs() - self.infoBox.setText("SciHub inaccessible - verify your connexion", 'error') - return - # Actual processing... + """ + Download and process academic articles from DOIs using Sci-Hub. + + This method handles the full pipeline for downloading PDFs via Sci-Hub, + extracting their text content, and converting them into LTTL-compatible + input segmentations. + + Steps: + 1. Verifies Sci-Hub accessibility. + 2. Downloads PDFs for each DOI. + 3. Extracts text from each PDF using pdfplumber. + 4. Wraps extracted text into LTTL.Inputs with DOI annotations. + 5. Concatenates inputs if multiple DOIs are processed. + + Returns : + Segmentation: A single or concatenated segmentation(s) ready for output. + + Raises: + Emits error messages and halts processing if: + - Sci-Hub is unreachable. + - A download fails. + - A PDF cannot be parsed. + """ - # For each progress bar iteration... - tempdir = tempfile.TemporaryDirectory() - for DOI in self.DOIs: + # At start of processing, set progress bar to 1%. + # Within this method, this is done using the following + # instruction. + self.signal_prog.emit(1, False) - # Update progress bar manually... - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - cur_itr += 1 + # DOIList.append(self.DOIContent) + + # Indicate the total number of iterations that the + # progress bar will go through (e.g. number of input + # segments, number of selected files, etc.), then + # set current iteration to 1. + max_itr = len(self.DOIs) + cur_itr = 1 + + # Permet de tester la connexion à Sci-Hub + if not test_scihub_accessible(): + self.sendNoneToOutputs() + self.infoBox.setText("SciHub inaccessible - verify your connexion", 'error') + return + # Actual processing... + + # For each progress bar iteration... + tempdir = tempfile.TemporaryDirectory() + for DOI in self.DOIs: + + # Update progress bar manually... + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + cur_itr += 1 + + # code ajouté ici + paper = DOI + paper_type = "doi" + out = f"{tempdir.name}/{self.DOIs.index(DOI)}" + try: + scihub_download(paper, paper_type=paper_type, out=out) + except Exception as ex: + print(ex) + self.sendNoneToOutputs() + self.infoBox.setText("An error occurred when downloading", 'error') + return + # Cancel operation if requested by user... + time.sleep(0.00001) # Needed somehow! + if self.cancel_operation: + self.signal_prog.emit(100, False) + return - # code ajouté ici - paper = DOI - paper_type = "doi" - out = f"{tempdir.name}/{self.DOIs.index(DOI)}" + # Update infobox and reset progress bar... + self.signal_text.emit(f"Step 2/3: Processing...", + "warning") + cur_itr = 0 + cur_itr_p3 = 0 + self.signal_prog.emit(0, True) + empty_re = False + for DOI in self.DOIs: + DOIText = "" + if os.path.exists(f"{tempdir.name}/{self.DOIs.index(DOI)}.pdf"): try: - scihub_download(paper, paper_type=paper_type, out=out) - except Exception as ex: - print(ex) + with pdfplumber.open(f"{tempdir.name}/{self.DOIs.index(DOI)}.pdf") as pdf: + for page in pdf.pages: + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + cur_itr += (1 / len(pdf.pages)) + DOIText += page.extract_text() + except Exception as e: self.sendNoneToOutputs() - self.infoBox.setText("An error occurred when downloading", 'error') - return - # Cancel operation if requested by user... - time.sleep(0.00001) # Needed somehow! - if self.cancel_operation: - self.signal_prog.emit(100, False) + self.infoBox.setText(f"Error occurred when reading PDF: {str(e)}", 'error') return + else: + self.sendNoneToOutputs() + self.infoBox.setText("Download failed. Please, verify DOI or connexion", 'error') + return + ######## + + # Create an LTTL.Input... + if len(self.DOIs) == 1: + # self.captionTitle is the name of the widget, + # which will become the label of the output + # segmentation. + label = self.captionTitle + else: + label = None # will be set later. - # Update infobox and reset progress bar... - self.signal_text.emit(f"Step 2/3: Processing...", + myInput = Input(DOIText, label) + + self.signal_text.emit("Step 3/3: Post-processing...", "warning") - cur_itr = 0 - self.signal_prog.emit(0, True) - empty_re = False - for DOI in self.DOIs: - DOIText = "" - if os.path.exists(f"{tempdir.name}/{self.DOIs.index(DOI)}.pdf"): - try: - with pdfplumber.open(f"{tempdir.name}/{self.DOIs.index(DOI)}.pdf") as pdf: - for page in pdf.pages: - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - cur_itr += (1 / len(pdf.pages)) - DOIText += page.extract_text() - except Exception as e: - self.sendNoneToOutputs() - self.infoBox.setText(f"Error occurred when reading PDF: {str(e)}", 'error') - return + max_itr = (int(self.importAll) + int(self.importBibliography))*(len(self.DOIs)+1) #+ int(self.importText) + if self.importAll: + + cur_itr_p3 += 1*len(self.DOIs) + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. + segment = myInput[0] + segment.annotations["DOI"] \ + = DOI + # For the annotation to be saved in the LTTL.Input, + # the extracted and annotated segment must be re-assigned + # to the first (and only) segment of the LTTL.Input. + myInput[0] = segment + # Add the LTTL.Input to self.createdInputs. + self.createdInputs.append(myInput) + if self.importBibliography: + cur_itr_p3 += 1*len(self.DOIs) + ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') + regexes = [(ma_regex, 'tokenize')] + self.signal_prog.emit(int(100 * cur_itr_p3 / max_itr), False) + new_segmentation = tokenize(myInput, regexes) + if (len(new_segmentation) == 0): + empty_re = True + new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") else: - self.sendNoneToOutputs() - self.infoBox.setText("Download failed. Please, verify DOI or connexion", 'error') - return - ######## - - # Create an LTTL.Input... - if len(self.DOIs) == 1: - # self.captionTitle is the name of the widget, - # which will become the label of the output - # segmentation. - label = self.captionTitle + new_input = Input(new_segmentation.to_string(), "Bibliographies") + segment = new_input[0] + segment.annotations["part"] = "Bibliography" + segment.annotations["DOI"] = DOI + new_input[0] = segment + self.createdInputs.append(new_input) + """if self.importText: + cur_itr += 1 + ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') + regexes = [(ma_regex,'tokenize')] + self.signal_prog.emit(int(100 * cur_itr / max_itr), False) + new_segmentation = tokenize(myInput, regexes) + print("*" * 100) + print(len(new_segmentation)) + print(new_segmentation.to_string()) + if(len(new_segmentation) == 0): + print("cucou") + empty_re = True + new_input = Input("","Empty Top level sections") else: - label = None # will be set later. - + new_segmentation[0].annotations["DOI"] = "Top level sections" + new_input = Input(new_segmentation.to_string(), "") + new_input[0]= new_segmentation[0] + self.createdInputs.append(new_segmentation)""" + """if self.importAbstract: + cur_itr += 1 myInput = Input(DOIText, label) - self.signal_text.emit("Step 3/3: Post-processing...", - "warning") - cur_itr = 0 - self.signal_prog.emit(0, True) - max_itr = int(self.importAll) + int(self.importBibliography) #+ int(self.importText) - if self.importAll: - - cur_itr += 1 - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput) - if self.importBibliography: - cur_itr += 1 - ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') - regexes = [(ma_regex, 'tokenize')] - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - if (len(new_segmentation) == 0): - empty_re = True - new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") - else: - new_segmentation[0].annotations["part"] = "Bibliography" - new_input = Input(new_segmentation.to_string(), "Bibliographies") - new_input[0].annotations["part"] = "Bibliography" - new_input[0] = new_segmentation[0] - self.createdInputs.append(new_input) - """if self.importText: - cur_itr += 1 - ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') - regexes = [(ma_regex,'tokenize')] - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - print("*" * 100) - print(len(new_segmentation)) - print(new_segmentation.to_string()) - if(len(new_segmentation) == 0): - print("cucou") - empty_re = True - new_input = Input("","Empty Top level sections") - else: - new_segmentation[0].annotations["DOI"] = "Top level sections" - new_input = Input(new_segmentation.to_string(), "") - new_input[0]= new_segmentation[0] - self.createdInputs.append(new_segmentation)""" - """if self.importAbstract: - cur_itr += 1 - myInput = Input(DOIText, label) - - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment - - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput)""" - - # Cancel operation if requested by user... - time.sleep(0.00001) # Needed somehow! - if self.cancel_operation: - self.signal_prog.emit(100, False) - return - tempdir.cleanup() - - - # If there's only one LTTL.Input created, it is the - # widget's output... - print(empty_re) - if empty_re: - QMessageBox.warning( - None, "SciHubator", "Not all sections were segmented", - QMessageBox.Ok - ) - if len(self.DOIs) == 1: - return self.createdInputs[0] - # Otherwise the widget's output is a concatenation... - else: - return Segmenter.concatenate( - caller=self, - segmentations=self.createdInputs, - label=self.captionTitle, - import_labels_as=None, - ) + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. + segment = myInput[0] + segment.annotations["DOI"] \ + = DOI + # For the annotation to be saved in the LTTL.Input, + # the extracted and annotated segment must be re-assigned + # to the first (and only) segment of the LTTL.Input. + myInput[0] = segment + + # Add the LTTL.Input to self.createdInputs. + self.createdInputs.append(myInput)""" + + # Cancel operation if requested by user... + time.sleep(0.00001) # Needed somehow! + if self.cancel_operation: + self.signal_prog.emit(100, False) + return + tempdir.cleanup() + + + # If there's only one LTTL.Input created, it is the + # widget's output... + print(empty_re) + if empty_re: + QMessageBox.warning( + None, "SciHubator", "Not all sections were segmented", + QMessageBox.Ok + ) + if len(self.DOIs) == 1: + return self.createdInputs[0] + # Otherwise the widget's output is a concatenation... + else: + return Segmenter.concatenate( + caller=self, + segmentations=self.createdInputs, + label=self.captionTitle, + import_labels_as=None, + ) @OWTextableBaseWidget.task_decorator def task_finished(self, f): - """All operations following the successful termination - of self.processData + """ + Handle the output after asynchronous DOI processing is complete. + + This method : + - Retrieves the result of the processing task. + - Calculates the number of segments and total characters. + - Displays an informative message to the user. + - Sends the processed data to the output. + + Args : + f (Future): A Future object containing the result from `processData`. + """ # Get the result value of self.processData. @@ -511,7 +571,15 @@ def task_finished(self, f): # The following method should be copied verbatim in # every Textable widget. def setCaption(self, title): - """Register captionTitle changes and send if needed""" + """ + Set or update the widget's caption title. + + If the caption has changed, it triggers cancellation of ongoing tasks + and marks the settings as changed to prompt UI updates. + + Args : + title (str): The new caption/title to be displayed on the widget. + """ if 'captionTitle' in dir(self): changed = title != self.captionTitle super().setCaption(title) @@ -522,7 +590,12 @@ def setCaption(self, title): super().setCaption(title) def clearAll(self): - """Remove all DOIs from DOIs attr""" + """ + Clear all stored DOIs and reset related UI elements. + + This method empties the DOI list and selection, + disables the 'Clear All' button, and updates the interface state. + """ del self.DOIs[:] del self.selectedURLLabel[:] self.sendButton.settingsChanged() @@ -531,7 +604,13 @@ def clearAll(self): self.removeButton.setDisabled(True) def remove(self): - """Remove URL from DOIs attr""" + """ + Remove the selected DOI from the list. + + Removes the DOI corresponding to the currently selected index in the GUI, + updates the list of DOIs and labels, and disables the clear button if the + list is empty. + """ if self.selectedURLLabel: index = self.selectedURLLabel[0] self.DOIs.pop(index) @@ -541,7 +620,13 @@ def remove(self): self.clearAllButton.setDisabled(not bool(self.URLLabel)) def add(self): - """Add DOIs to DOIs attr""" + """ + Add new DOI(s) from the input field to the list. + + Parses the input string for comma-separated DOIs, adds them to the internal list, + removes duplicates if any, updates the display labels, and enables relevant UI buttons. + Shows a message box if duplicates are found and removed. + """ DOIList = [x.strip() for x in self.newDOI.strip().split(',')] print(DOIList) #--> Pas besoin de la boucle DOIList non?? <-- @@ -581,6 +666,9 @@ def onDeleteWidget(self): """Clear created inputs on widget deletion""" self.clearCreatedInputs() def test_scihub_accessible(): + """ + Test the internet connection and/or sci-hub's accessibility. + """ try: response = requests.get("https://sci-hub.se", timeout=10) return response.status_code == 200 From 3f217b46ef8dfa0534dd728c0fb7ebe6f783b23d Mon Sep 17 00:00:00 2001 From: ColinLug Date: Fri, 23 May 2025 01:07:22 +0200 Subject: [PATCH 78/86] =?UTF-8?q?orso=20doc=20ajout=C3=A9e=20part.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- orangecontrib/textable_prototypes/widgets/SciHubatorTest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 7a139325..b5b9c1f4 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -264,8 +264,8 @@ def __init__(self): widget=advOptionsBox, master=self, value='importAllorBib', - btnLabels=['Bib', 'All'], - label=u'Bibliography', + btnLabels=['All in one Segment', 'Bibliography'], + label=u'Choose what to import', callback=self.sendButton.settingsChanged, tooltips=["Import all article's in one segment", "Import only bibliography (if found)"] ) From b3e296bb03110ea62efd068ff9e9616179f25812 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Tue, 3 Jun 2025 14:09:37 +0200 Subject: [PATCH 79/86] chais pas --- .../widgets/SciHubatorTest.py | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index b5b9c1f4..79ddea55 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -267,7 +267,7 @@ def __init__(self): btnLabels=['All in one Segment', 'Bibliography'], label=u'Choose what to import', callback=self.sendButton.settingsChanged, - tooltips=["Import all article's in one segment", "Import only bibliography (if found)"] + tooltips=["Import all article's content in one segment", "Import only bibliography (if found)"] ) gui.separator(widget=addURLBox, height=3) self.addButton = gui.button( @@ -445,7 +445,37 @@ def processData(self): self.signal_text.emit("Step 3/3: Post-processing...", "warning") max_itr = (int(self.importAll) + int(self.importBibliography))*(len(self.DOIs)+1) #+ int(self.importText) - if self.importAll: + if self.importAllorBib == 0: + cur_itr_p3 += 1 * len(self.DOIs) + # Extract the first (and single) segment in the + # newly created LTTL.Input and annotate it with + # the length of the input segmentation. + segment = myInput[0] + segment.annotations["DOI"] \ + = DOI + # For the annotation to be saved in the LTTL.Input, + # the extracted and annotated segment must be re-assigned + # to the first (and only) segment of the LTTL.Input. + myInput[0] = segment + # Add the LTTL.Input to self.createdInputs. + self.createdInputs.append(myInput) + if self.importAllorBib == 1: + cur_itr_p3 += 1 * len(self.DOIs) + ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') + regexes = [(ma_regex, 'tokenize')] + self.signal_prog.emit(int(100 * cur_itr_p3 / max_itr), False) + new_segmentation = tokenize(myInput, regexes) + if (len(new_segmentation) == 0): + empty_re = True + new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") + else: + new_input = Input(new_segmentation.to_string(), "Bibliographies") + segment = new_input[0] + segment.annotations["part"] = "Bibliography" + segment.annotations["DOI"] = DOI + new_input[0] = segment + self.createdInputs.append(new_input) + """if self.importAll: cur_itr_p3 += 1*len(self.DOIs) # Extract the first (and single) segment in the @@ -475,7 +505,7 @@ def processData(self): segment.annotations["part"] = "Bibliography" segment.annotations["DOI"] = DOI new_input[0] = segment - self.createdInputs.append(new_input) + self.createdInputs.append(new_input)""" """if self.importText: cur_itr += 1 ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') @@ -486,7 +516,6 @@ def processData(self): print(len(new_segmentation)) print(new_segmentation.to_string()) if(len(new_segmentation) == 0): - print("cucou") empty_re = True new_input = Input("","Empty Top level sections") else: From 5cd168df97c52185bdcd92d366a3272c507b9e3e Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Tue, 3 Jun 2025 14:23:57 +0200 Subject: [PATCH 80/86] this is not going well --- .../widgets/SciHubatorTest.py | 67 +------------------ 1 file changed, 1 insertion(+), 66 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 79ddea55..f6636a21 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -98,8 +98,6 @@ class SciHubator(OWTextableBaseWidget): # Ici-dessous les variables qui n'ont pas été copiées, et conçues spécialement pour SciHubator """importAll = Setting(True)""" - """importAbstract = Setting(False)""" - """importText = Setting(False)""" """importBibliography = Setting(False)""" importAllorBib = Setting(0) @@ -224,30 +222,6 @@ def __init__(self): ), )""" """gui.separator(widget=advOptionsBox, height=3) - gui.checkBox( - widget=advOptionsBox, - master=self, - value='importAbstract', - label=u'Abstract', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"Output Abstract as a segmentation." - ), - )""" - """gui.separator(widget=advOptionsBox, height=3) - gui.checkBox( - widget=advOptionsBox, - master=self, - value='importText', - label=u'Top Level Sections', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"output main text as a segmentation." - ), - )""" - """gui.separator(widget=advOptionsBox, height=3) gui.checkBox( widget=advOptionsBox, master=self, @@ -299,11 +273,6 @@ def sendData(self): - Updates the UI to indicate the start of preprocessing. - Launches the processing asynchronously using a background thread """ - # Verify checkboxes - if not (self.importAll or self.importBibliography): #or self.importText - self.infoBox.setText("Please select one or more checkboxes.", "warning") - self.send("Segmentation", None) - return # Verify DOIs if not self.DOIs: self.infoBox.setText("Please enter one or many valid DOIs.", "warning") @@ -444,7 +413,7 @@ def processData(self): self.signal_text.emit("Step 3/3: Post-processing...", "warning") - max_itr = (int(self.importAll) + int(self.importBibliography))*(len(self.DOIs)+1) #+ int(self.importText) + max_itr = (int(self.importAllorBib)) if self.importAllorBib == 0: cur_itr_p3 += 1 * len(self.DOIs) # Extract the first (and single) segment in the @@ -506,40 +475,6 @@ def processData(self): segment.annotations["DOI"] = DOI new_input[0] = segment self.createdInputs.append(new_input)""" - """if self.importText: - cur_itr += 1 - ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') - regexes = [(ma_regex,'tokenize')] - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - print("*" * 100) - print(len(new_segmentation)) - print(new_segmentation.to_string()) - if(len(new_segmentation) == 0): - empty_re = True - new_input = Input("","Empty Top level sections") - else: - new_segmentation[0].annotations["DOI"] = "Top level sections" - new_input = Input(new_segmentation.to_string(), "") - new_input[0]= new_segmentation[0] - self.createdInputs.append(new_segmentation)""" - """if self.importAbstract: - cur_itr += 1 - myInput = Input(DOIText, label) - - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment - - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput)""" # Cancel operation if requested by user... time.sleep(0.00001) # Needed somehow! From 4b2509a3cb335728fbd9fa21ac517e93e13ea407 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Tue, 3 Jun 2025 15:22:48 +0200 Subject: [PATCH 81/86] progress_bar part 3 works? --- .../widgets/SciHubatorTest.py | 81 ++----------------- 1 file changed, 5 insertions(+), 76 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 79ddea55..0192b3ee 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -299,11 +299,6 @@ def sendData(self): - Updates the UI to indicate the start of preprocessing. - Launches the processing asynchronously using a background thread """ - # Verify checkboxes - if not (self.importAll or self.importBibliography): #or self.importText - self.infoBox.setText("Please select one or more checkboxes.", "warning") - self.send("Segmentation", None) - return # Verify DOIs if not self.DOIs: self.infoBox.setText("Please enter one or many valid DOIs.", "warning") @@ -376,7 +371,7 @@ def processData(self): # Permet de tester la connexion à Sci-Hub if not test_scihub_accessible(): self.sendNoneToOutputs() - self.infoBox.setText("SciHub inaccessible - verify your connexion", 'error') + self.infoBox.setText("SciHub inaccessible - vérifiez votre connexion", 'error') return # Actual processing... @@ -444,9 +439,9 @@ def processData(self): self.signal_text.emit("Step 3/3: Post-processing...", "warning") - max_itr = (int(self.importAll) + int(self.importBibliography))*(len(self.DOIs)+1) #+ int(self.importText) + max_itr = 2*len(self.DOIs) #+ int(self.importText) if self.importAllorBib == 0: - cur_itr_p3 += 1 * len(self.DOIs) + cur_itr_p3 += 1 # Extract the first (and single) segment in the # newly created LTTL.Input and annotate it with # the length of the input segmentation. @@ -460,7 +455,7 @@ def processData(self): # Add the LTTL.Input to self.createdInputs. self.createdInputs.append(myInput) if self.importAllorBib == 1: - cur_itr_p3 += 1 * len(self.DOIs) + cur_itr_p3 += 1 ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') regexes = [(ma_regex, 'tokenize')] self.signal_prog.emit(int(100 * cur_itr_p3 / max_itr), False) @@ -475,72 +470,6 @@ def processData(self): segment.annotations["DOI"] = DOI new_input[0] = segment self.createdInputs.append(new_input) - """if self.importAll: - - cur_itr_p3 += 1*len(self.DOIs) - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput) - if self.importBibliography: - cur_itr_p3 += 1*len(self.DOIs) - ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') - regexes = [(ma_regex, 'tokenize')] - self.signal_prog.emit(int(100 * cur_itr_p3 / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - if (len(new_segmentation) == 0): - empty_re = True - new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") - else: - new_input = Input(new_segmentation.to_string(), "Bibliographies") - segment = new_input[0] - segment.annotations["part"] = "Bibliography" - segment.annotations["DOI"] = DOI - new_input[0] = segment - self.createdInputs.append(new_input)""" - """if self.importText: - cur_itr += 1 - ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') - regexes = [(ma_regex,'tokenize')] - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - print("*" * 100) - print(len(new_segmentation)) - print(new_segmentation.to_string()) - if(len(new_segmentation) == 0): - empty_re = True - new_input = Input("","Empty Top level sections") - else: - new_segmentation[0].annotations["DOI"] = "Top level sections" - new_input = Input(new_segmentation.to_string(), "") - new_input[0]= new_segmentation[0] - self.createdInputs.append(new_segmentation)""" - """if self.importAbstract: - cur_itr += 1 - myInput = Input(DOIText, label) - - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment - - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput)""" - # Cancel operation if requested by user... time.sleep(0.00001) # Needed somehow! if self.cancel_operation: @@ -696,7 +625,7 @@ def test_scihub_accessible(): Test the internet connection and/or sci-hub's accessibility. """ try: - response = requests.get("https://sci-hub.se", timeout=10) + response = requests.get("https://sci-hub.st", timeout=10) return response.status_code == 200 except: return False From 1e17d0f6a1b5a1f4f5115f142e4275307b56a855 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Tue, 3 Jun 2025 15:26:37 +0200 Subject: [PATCH 82/86] specs like before --- specs/Sci-Hubator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/Sci-Hubator.rst b/specs/Sci-Hubator.rst index 3b73be41..3228770f 100644 --- a/specs/Sci-Hubator.rst +++ b/specs/Sci-Hubator.rst @@ -76,7 +76,7 @@ Créer un widget pour Orange Textable (v3.2.2) permettant l'importation et l'ext 2.3 Fonctionnalités principales =============================== -.. image:: images/scihubator_principal.png +.. image:: images/scihubator_principal_specs.png * permettre l'importation de pdf tirés de SCI-HUB (à partir d'un DOI). * permettre d'en tirer le texte. From 5f27378c305513fe7281458e9acc80a4971aeac4 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Tue, 3 Jun 2025 15:37:24 +0200 Subject: [PATCH 83/86] petit ajout pour les radiobuttons --- .../widgets/SciHubatorTest.py | 2 +- specs/images/scihubator_principal_specs.png | Bin 0 -> 34792 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 specs/images/scihubator_principal_specs.png diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index 0192b3ee..a2b0b9f1 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -38,7 +38,7 @@ from scidownl import scihub_download from _textable.widgets.TextableUtils import ( OWTextableBaseWidget, - InfoBox, SendButton, pluralize + InfoBox, SendButton, pluralize #, processRadioButtons (un truc dans le genre), sûrement callback de radiobuttons ) from LTTL.Segmenter import tokenize from LTTL.Segmentation import Segmentation diff --git a/specs/images/scihubator_principal_specs.png b/specs/images/scihubator_principal_specs.png new file mode 100644 index 0000000000000000000000000000000000000000..59d95c7709c248a2b817e1cbf42d2bb1f8a55439 GIT binary patch literal 34792 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ÑWaNtI5FLxfvC*FMpsn*Um=tx;{=NA3$LaL6 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 literal 0 HcmV?d00001 From 49401e979890992c4683b365163d5a67920d1535 Mon Sep 17 00:00:00 2001 From: sarahperettipoix <114944575+sarahperettipoix@users.noreply.github.com> Date: Thu, 5 Jun 2025 10:29:26 +0200 Subject: [PATCH 84/86] this is not going well --- .../widgets/SciHubatorTest.py | 122 +----------------- 1 file changed, 5 insertions(+), 117 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index bbb32c43..c986ccb1 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -38,7 +38,7 @@ from scidownl import scihub_download from _textable.widgets.TextableUtils import ( OWTextableBaseWidget, - InfoBox, SendButton, pluralize #, processRadioButtons (un truc dans le genre), sûrement callback de radiobuttons + InfoBox, SendButton, pluralize ) from LTTL.Segmenter import tokenize from LTTL.Segmentation import Segmentation @@ -201,8 +201,8 @@ def __init__(self): tooltip=( u"The DOI(s) that will be added to the list when\n" u"button 'Add' is clicked.\n\n" - u"Successive DOIs must be separated with ' / ' \n" - u"(space + slash + space). Their order in the list\n" + u"Successive DOIs must be separated with ' , '. \n" + u"Their order in the list\n" u" will be the same as in this field." ), ) @@ -212,53 +212,6 @@ def __init__(self): orientation='vertical', addSpace=False, ) - """gui.checkBox( - widget=advOptionsBox, - master=self, - value='importAll', - label=u'All in one Segment', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"Output entire text as a single segmentation." - ), - )""" - """gui.separator(widget=advOptionsBox, height=3) - gui.checkBox( - widget=advOptionsBox, - master=self, - value='importAbstract', - label=u'Abstract', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"Output Abstract as a segmentation." - ), - )""" - """gui.separator(widget=advOptionsBox, height=3) - gui.checkBox( - widget=advOptionsBox, - master=self, - value='importText', - label=u'Top Level Sections', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"output main text as a segmentation." - ), - )""" - """gui.separator(widget=advOptionsBox, height=3) - gui.checkBox( - widget=advOptionsBox, - master=self, - value='importBibliography', - label=u'Bibliography', - labelWidth=180, - callback=self.sendButton.settingsChanged, - tooltip=( - u"output bibliography as a segmentation." - ), - )""" gui.separator(widget=advOptionsBox, height=3) gui.radioButtonsInBox( widget=advOptionsBox, @@ -276,7 +229,7 @@ def __init__(self): label=u'Add', callback=self.add, tooltip=( - u"Add the DOI currently displayed in the 'DOI'\n" + u"Add the DOI(s) currently displayed in the 'DOI'\n" u"text field to the list." ), disabled = True, @@ -444,7 +397,7 @@ def processData(self): self.signal_text.emit("Step 3/3: Post-processing...", "warning") - max_itr = (int(self.importAll) + int(self.importBibliography))*(len(self.DOIs)+1) #+ int(self.importText) + max_itr = (2*int(importAllorBib)) if self.importAllorBib == 0: cur_itr_p3 += 1 * len(self.DOIs) # Extract the first (and single) segment in the @@ -475,71 +428,6 @@ def processData(self): segment.annotations["DOI"] = DOI new_input[0] = segment self.createdInputs.append(new_input) - """if self.importAll: - - cur_itr_p3 += 1*len(self.DOIs) - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput) - if self.importBibliography: - cur_itr_p3 += 1*len(self.DOIs) - ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') - regexes = [(ma_regex, 'tokenize')] - self.signal_prog.emit(int(100 * cur_itr_p3 / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - if (len(new_segmentation) == 0): - empty_re = True - new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") - else: - new_input = Input(new_segmentation.to_string(), "Bibliographies") - segment = new_input[0] - segment.annotations["part"] = "Bibliography" - segment.annotations["DOI"] = DOI - new_input[0] = segment - self.createdInputs.append(new_input)""" - """if self.importText: - cur_itr += 1 - ma_regex = re.compile(r'(.|\n)*(?=([Bb]iblio|[Rr][eé]f))') - regexes = [(ma_regex,'tokenize')] - self.signal_prog.emit(int(100 * cur_itr / max_itr), False) - new_segmentation = tokenize(myInput, regexes) - print("*" * 100) - print(len(new_segmentation)) - print(new_segmentation.to_string()) - if(len(new_segmentation) == 0): - empty_re = True - new_input = Input("","Empty Top level sections") - else: - new_segmentation[0].annotations["DOI"] = "Top level sections" - new_input = Input(new_segmentation.to_string(), "") - new_input[0]= new_segmentation[0] - self.createdInputs.append(new_segmentation)""" - """if self.importAbstract: - cur_itr += 1 - myInput = Input(DOIText, label) - - # Extract the first (and single) segment in the - # newly created LTTL.Input and annotate it with - # the length of the input segmentation. - segment = myInput[0] - segment.annotations["DOI"] \ - = DOI - # For the annotation to be saved in the LTTL.Input, - # the extracted and annotated segment must be re-assigned - # to the first (and only) segment of the LTTL.Input. - myInput[0] = segment - - # Add the LTTL.Input to self.createdInputs. - self.createdInputs.append(myInput)""" # Cancel operation if requested by user... time.sleep(0.00001) # Needed somehow! From e96d360235b90f481dee31b629366a50ace4d106 Mon Sep 17 00:00:00 2001 From: ColinLug Date: Thu, 5 Jun 2025 10:55:00 +0200 Subject: [PATCH 85/86] final --- .../widgets/SciHubatorTest.py | 124 ++++++++---------- 1 file changed, 58 insertions(+), 66 deletions(-) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py index c986ccb1..8ac497cd 100644 --- a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py +++ b/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py @@ -20,31 +20,31 @@ . """ -__version__ = u"0.0.1" +__version__ = "0.0.1" __author__ = "Sarah Perreti-Poix, Borgeaud Matthias, Chétioui Orsowen, Luginbühl Colin" __maintainer__ = "Aris Xanthos" __email__ = "aris.xanthos@unil.ch" -import re # Standard imports... +import re import time import tempfile -import pdfplumber import os -import requests -import LTTL.SegmenterThread as Segmenter from functools import partial +import pdfplumber +import requests from scidownl import scihub_download from _textable.widgets.TextableUtils import ( OWTextableBaseWidget, InfoBox, SendButton, pluralize ) +import LTTL.SegmenterThread as Segmenter from LTTL.Segmenter import tokenize from LTTL.Segmentation import Segmentation -from Orange.widgets import widget, gui, settings -from Orange.widgets.utils.widgetpreview import WidgetPreview from LTTL.Input import Input +from Orange.widgets import gui, settings +from Orange.widgets.utils.widgetpreview import WidgetPreview from Orange.widgets.settings import Setting from PyQt5.QtWidgets import QMessageBox @@ -81,7 +81,7 @@ class SciHubator(OWTextableBaseWidget): # GUI layout parameters... want_main_area = False - resizing_enabled = False + resizing_enabled = True # ---------------------------------------------------------------------- # Settings declaration and initializations (default values)... @@ -89,18 +89,14 @@ class SciHubator(OWTextableBaseWidget): DOIs = Setting([]) encoding = Setting('(auto-detect)') autoNumber = Setting(False) - autoNumberKey = Setting(u'num') + autoNumberKey = Setting('num') autoSend = settings.Setting(False) importDOIs = Setting(True) - importDOIsKey = Setting(u'url') + importDOIsKey = Setting('url') lastLocation = Setting('.') - DOI = Setting(u'') + DOI = Setting('') # Ici-dessous les variables qui n'ont pas été copiées, et conçues spécialement pour SciHubator - """importAll = Setting(True)""" - """importAbstract = Setting(False)""" - """importText = Setting(False)""" - """importBibliography = Setting(False)""" importAllorBib = Setting(0) def __init__(self): @@ -110,11 +106,11 @@ def __init__(self): super().__init__() self.URLLabel = self.DOIs[:] print(self.URLLabel) - self.selectedURLLabel = list() - self.newDOI = u'' - self.extractedText = u'' - self.DOI = u'' - self.createdInputs = list() + self.selectedURLLabel = [] + self.newDOI = '' + self.extractedText = '' + self.DOI = '' + self.createdInputs = [] self.infoBox = InfoBox(widget=self.controlArea) self.sendButton = SendButton( @@ -132,7 +128,7 @@ def __init__(self): # URL box URLBox = gui.widgetBox( widget=self.controlArea, - box=u'Sources', + box='Sources', orientation='vertical', addSpace=False, ) @@ -149,9 +145,9 @@ def __init__(self): labels='URLLabel', callback=self.updateURLBoxButtons, tooltip=( - u"The list of DOIs whose content will be imported.\n" - u"\nIn the output segmentation, the content of each\n" - u"DOI appears in the same position as in the list.\n" + "The list of DOIs whose content will be imported.\n" + "\nIn the output segmentation, the content of each\n" + "DOI appears in the same position as in the list.\n" ), ) URLBoxCol2 = gui.widgetBox( @@ -161,20 +157,20 @@ def __init__(self): self.removeButton = gui.button( widget=URLBoxCol2, master=self, - label=u'Remove', + label='Remove', callback=self.remove, tooltip=( - u"Remove the selected DOI from the list." + "Remove the selected DOI from the list." ), disabled = True, ) self.clearAllButton = gui.button( widget=URLBoxCol2, master=self, - label=u'Clear All', + label='Clear All', callback=self.clearAll, tooltip=( - u"Remove all DOIs from the list." + "Remove all DOIs from the list." ), disabled = True, ) @@ -195,20 +191,20 @@ def __init__(self): master=self, value='newDOI', orientation='horizontal', - label=u'DOI(s):', + label='DOI(s):', labelWidth=101, callback=self.updateURLBoxButtons, tooltip=( - u"The DOI(s) that will be added to the list when\n" - u"button 'Add' is clicked.\n\n" - u"Successive DOIs must be separated with ' , '. \n" - u"Their order in the list\n" - u" will be the same as in this field." + "The DOI(s) that will be added to the list when\n" + "button 'Add' is clicked.\n\n" + "Successive DOIs must be separated with ' , '. \n" + "Their order in the list\n" + " will be the same as in this field." ), ) advOptionsBox = gui.widgetBox( widget=self.controlArea, - box=u'Options', + box='Options', orientation='vertical', addSpace=False, ) @@ -218,19 +214,21 @@ def __init__(self): master=self, value='importAllorBib', btnLabels=['All in one Segment', 'Bibliography'], - label=u'Choose what to import', + label='Choose what to import', callback=self.sendButton.settingsChanged, - tooltips=["Import all article's content in one segment", "Import only bibliography (if found)"] + tooltips=[ + "Import all article's content in one segment", "Import only bibliography (if found)" + ] ) gui.separator(widget=addURLBox, height=3) self.addButton = gui.button( widget=addURLBox, master=self, - label=u'Add', + label='Add', callback=self.add, tooltip=( - u"Add the DOI(s) currently displayed in the 'DOI'\n" - u"text field to the list." + "Add the DOI(s) currently displayed in the 'DOI'\n" + "text field to the list." ), disabled = True, ) @@ -252,11 +250,6 @@ def sendData(self): - Updates the UI to indicate the start of preprocessing. - Launches the processing asynchronously using a background thread """ - # Verify checkboxes - if not (self.importAll or self.importBibliography): #or self.importText - self.infoBox.setText("Please select one or more checkboxes.", "warning") - self.send("Segmentation", None) - return # Verify DOIs if not self.DOIs: self.infoBox.setText("Please enter one or many valid DOIs.", "warning") @@ -270,7 +263,7 @@ def sendData(self): # processing" and "post-processing" steps before and # after it. If there are no optional steps, notify # "Preprocessing...". - self.infoBox.setText(f"Step 1/3: Pre-processing...", "warning") + self.infoBox.setText("Step 1/3: Pre-processing...", "warning") # Progress bar should be initialized at this point. self.progressBarInit() @@ -359,7 +352,7 @@ def processData(self): return # Update infobox and reset progress bar... - self.signal_text.emit(f"Step 2/3: Processing...", + self.signal_text.emit("Step 2/3: Processing...", "warning") cur_itr = 0 cur_itr_p3 = 0 @@ -397,9 +390,9 @@ def processData(self): self.signal_text.emit("Step 3/3: Post-processing...", "warning") - max_itr = (2*int(importAllorBib)) + max_itr = 2*len(self.DOIs) #+ int(self.importText) if self.importAllorBib == 0: - cur_itr_p3 += 1 * len(self.DOIs) + cur_itr_p3 += 1 # Extract the first (and single) segment in the # newly created LTTL.Input and annotate it with # the length of the input segmentation. @@ -413,14 +406,16 @@ def processData(self): # Add the LTTL.Input to self.createdInputs. self.createdInputs.append(myInput) if self.importAllorBib == 1: - cur_itr_p3 += 1 * len(self.DOIs) + cur_itr_p3 += 1 ma_regex = re.compile(r'(?<=\n)\n?(([Bb]iblio|[Rr][eé]f)\w*\W*\n)(.|\n)*') regexes = [(ma_regex, 'tokenize')] self.signal_prog.emit(int(100 * cur_itr_p3 / max_itr), False) new_segmentation = tokenize(myInput, regexes) - if (len(new_segmentation) == 0): + if len(new_segmentation) == 0: empty_re = True - new_input = Input(f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section") + new_input = Input( + f"Empty search Bib for DOI: {DOI}", "Empty Bibliography section" + ) else: new_input = Input(new_segmentation.to_string(), "Bibliographies") segment = new_input[0] @@ -439,7 +434,6 @@ def processData(self): # If there's only one LTTL.Input created, it is the # widget's output... - print(empty_re) if empty_re: QMessageBox.warning( None, "SciHubator", "Not all sections were segmented", @@ -448,13 +442,12 @@ def processData(self): if len(self.DOIs) == 1: return self.createdInputs[0] # Otherwise the widget's output is a concatenation... - else: - return Segmenter.concatenate( - caller=self, - segmentations=self.createdInputs, - label=self.captionTitle, - import_labels_as=None, - ) + return Segmenter.concatenate( + caller=self, + segmentations=self.createdInputs, + label=self.captionTitle, + import_labels_as=None, + ) @OWTextableBaseWidget.task_decorator def task_finished(self, f): @@ -508,7 +501,8 @@ def clearAll(self): Clear all stored DOIs and reset related UI elements. This method empties the DOI list and selection, - disables the 'Clear All' button, and updates the interface state. + disables the 'Clear All' button, + and updates the interface state. """ del self.DOIs[:] del self.selectedURLLabel[:] @@ -542,14 +536,12 @@ def add(self): Shows a message box if duplicates are found and removed. """ DOIList = [x.strip() for x in self.newDOI.strip().split(',')] - print(DOIList) - #--> Pas besoin de la boucle DOIList non?? <-- + for DOI in DOIList: - print(DOI) self.DOIs.append(DOI) if self.DOIs: tempSet = set(self.DOIs) - if(len(tempSet) Date: Thu, 5 Jun 2025 10:55:40 +0200 Subject: [PATCH 86/86] final --- .../widgets/{SciHubatorTest.py => SciHubator.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename orangecontrib/textable_prototypes/widgets/{SciHubatorTest.py => SciHubator.py} (100%) diff --git a/orangecontrib/textable_prototypes/widgets/SciHubatorTest.py b/orangecontrib/textable_prototypes/widgets/SciHubator.py similarity index 100% rename from orangecontrib/textable_prototypes/widgets/SciHubatorTest.py rename to orangecontrib/textable_prototypes/widgets/SciHubator.py