diff --git a/.citation_parser_ui.py.swp b/.citation_parser_ui.py.swp deleted file mode 100644 index 38c0d61d4724d853b03e358ed4916b537560e72f..0000000000000000000000000000000000000000 Binary files a/.citation_parser_ui.py.swp and /dev/null differ diff --git a/assets/json_text.json b/assets/json_text.json index b2e4c5f1d417d21f23729da7e833989a82a9eeaf..b8177a35f64f22f16224949cf9e8c88ae7fdbe6b 100644 --- a/assets/json_text.json +++ b/assets/json_text.json @@ -1 +1 @@ -{"nodes": [{"doi": "https://doi.org/10.1021/acs.jcim.6b00709", "name": "Matched Molecular Series: Measuring SAR Similarity", "author": ["Emanuel S. R. Ehmki", "Christian Kramer"], "year": "May 1, 2017", "journal": "Journal of Chemical Information and Modeling", "group": "Input", "depth": 0, "citations": 5}, {"doi": "https://doi.org/10.1021/acs.jcim.0c00269", "name": "Matched Molecular Series Analysis for ADME Property Prediction", "author": ["Mahendra Awale", "Sereina Riniker", "Christian Kramer"], "year": "May 5, 2020", "journal": "Journal of Chemical Information and Modeling", "group": "Citedby", "depth": 1, "citations": 6}, {"doi": "https://doi.org/10.1021/acs.jcim.0c00290", "name": "Identification of Bioisosteric Substituents by a Deep Neural Network", "author": ["Peter Ertl"], "year": "June 15, 2020", "journal": "Journal of Chemical Information and Modeling", "group": "Citedby", "depth": 2, "citations": 2}], "links": [{"source": "https://doi.org/10.1021/acs.jcim.0c00269", "target": "https://doi.org/10.1021/acs.jcim.6b00709"}, {"source": "https://doi.org/10.1021/acs.jcim.0c00290", "target": "https://doi.org/10.1021/acs.jcim.0c00269"}]} \ No newline at end of file +{"nodes": [], "links": []} \ No newline at end of file diff --git a/citation_parser_ui.py b/citation_parser_ui.py index 2dbd0be7bee696f3a62a68f38ff3a50f6fc5e80c..c2b119dce5075fb6f1e11226dbf866abccd1d4fe 100644 --- a/citation_parser_ui.py +++ b/citation_parser_ui.py @@ -42,31 +42,31 @@ app.layout = html.Div([ is_open=False, ), - # Layer 1: For all mandatory Inputs + # Layer 1: For the string input html.Div([ "Input: ", # A simple box for inputting a string. # Value is transmitted upon pressing return or clicking out of the box. - dcc.Input(id='input-string', value='', type='text',debounce=True, + dcc.Input(id='string-input', value='', type='text',debounce=True, style={ "width": "400px"}, ), ]), - # Layer 1,5: For test + # Layer 2: For file input and recursion depths html.Div([ - "Forward recursion: ", + "Cited-by Depth: ", # Forward recursion. Values between 1 and 10 can be entered. - dcc.Input(id='forward-depth',value='1',type='number',min='1',max='10', + dcc.Input(id='forward-depth',value='1',type='number',min='0',max='5', style={ "width": "50px"}, ), - "Backward recursion: ", + "References Depth: ", # Backward recursion. Values between 1 and 10 can be entered. - dcc.Input(id='backward-depth',value='1',type='number',min='1',max='10', + dcc.Input(id='backward-depth',value='1',type='number',min='0',max='5', style={"width": "50px"}, ), # Upload box. Can be used via drag-and-drop or byclicking on it to open a file viewer. dcc.Upload( - id="upload-data", + id="file-input", children=html.Div( #Drag and drop or click to select a file to upload ["Drag and drop"]), @@ -82,7 +82,7 @@ app.layout = html.Div([ }) ]), - # Layer 2: For the checklist, Remove-/Start-Buttons and input-error-message + # Layer 3: For the checklist, Remove-/Start-Buttons and error message html.Div([ # All input DOIs are collected in this checklist. # It is initialized to avoid error messages. @@ -97,7 +97,7 @@ app.layout = html.Div([ # Starts the process that generates a graph. dbc.Button(id='start-button',children='Generate Graph', color="primary", className="me-1") ]), - # Layer 3: For additional Options (e.g. Topological Sort) + # Layer 4: For additional Options html.Div([ html.H4('Additional Options'), # A checklist of all additional options that are listed above. @@ -105,25 +105,25 @@ app.layout = html.Div([ options=[{'label':k,'value':k} for k in additional_options], value=[]) ]), - # Layer 4: For the Graph - html.Div( - [html.Iframe( + # Layer 5: For the Graph and corresponding error messages + html.Div([ + html.Div(id='generate-graph-error',style={'color':'red'}), + html.Iframe( src="assets/index.html", style={"height": "600px", "width": "100%"}, ), - html.Div(id='test-output') ]) ]) @app.callback( Output('input-checklist','options'), Output('input-checklist','value'), - Output('input-string','value'), + Output('string-input','value'), Output('input-err','children'), - Input('input-string','value'), + Input('string-input','value'), Input('clear-all-button','n_clicks'), Input('clear-selected-button','n_clicks'), - Input('upload-data','contents'), + Input('file-input','contents'), State('input-checklist','options'), State('input-checklist','value'), State('additional-options','value') @@ -133,7 +133,7 @@ def update_input_checklist(input_value,btn1,btn2,filecontents,all_inputs, ''' Most important callback function. Updates the checklist that holds all inputs. State of the checklist as input is needed so that previews entries are readded. - input-string is required as Output to clear the input box after each input. + string-input is required as Output to clear the input box after each input. Different actions are performed depending on which input triggered the callback. The value-attribute of input-checklist must be updates so that the values of deleted elements no longer appear in the list of selected elements. @@ -168,7 +168,7 @@ def update_input_checklist(input_value,btn1,btn2,filecontents,all_inputs, return all_inputs,list(),'','' # when a new element is added via dcc.Input - if 'input-string' in changed_id: + if 'string-input' in changed_id: # Creates a list of previously added inputs to make sure nothing is added twice currValues = [x['value'] for x in all_inputs] if input_value not in currValues: @@ -186,7 +186,10 @@ def update_input_checklist(input_value,btn1,btn2,filecontents,all_inputs, # Creates a more readable string to display in the checklist rep_str = pub.contributors[0] + ',' + pub.journal + \ ',' + pub.publication_date - all_inputs.append({'label':rep_str, 'value':input_value}) + # Makes sure not to add the same article with different links + currLabels = [x['label'] for x in all_inputs] + if rep_str not in currLabels: + all_inputs.append({'label':rep_str, 'value':input_value}) # if 'Smart Input' is not selected, the input value is added as is, # without checking for validity. @@ -195,7 +198,7 @@ def update_input_checklist(input_value,btn1,btn2,filecontents,all_inputs, return all_inputs,selected_inputs,'','' # when a txt-file is uploaded - if 'upload-data.contents' in changed_id: + if 'file-input.contents' in changed_id: if filecontents: # Skips the info portion that is added when a file is uploaded found = base64.b64decode(re.search(',(.+?)$', filecontents).group(1)) @@ -215,7 +218,9 @@ def update_input_checklist(input_value,btn1,btn2,filecontents,all_inputs, return all_inputs,selected_inputs,'','{}'.format(err) rep_str = pub.contributors[0] + ',' + pub.journal + \ ',' + pub.publication_date - all_inputs.append({'label':rep_str, 'value':input_value}) + currLabels = [x['label'] for x in all_inputs] + if rep_str not in currLabels: + all_inputs.append({'label':rep_str, 'value':input_value}) else: all_inputs.append({'label':input_value,'value':input_value}) return all_inputs,selected_inputs,'','' @@ -244,16 +249,14 @@ def toggle_collapse(n, is_open): @app.callback( - Output('test-output','children'), + Output('generate-graph-error','children'), Input('start-button','n_clicks'), Input('input-checklist','options'), - Input('input-checklist','value'), Input('forward-depth','value'), Input('backward-depth','value'), State('additional-options','value') ) -def generate_output(n_clicks,all_inputs,selected_inputs, - forward_depth,backward_depth,additional_options): +def generate_output(n_clicks,all_inputs,forward_depth,backward_depth,additional_options): ''' Basic structure for a callback that generates an output. This is only a proof of concept and has noting to do with the intended output yet. @@ -263,8 +266,6 @@ def generate_output(n_clicks,all_inputs,selected_inputs, :param all_inputs: all labels and values from the checklist, regardless if they have been checked or not :type all_inputs: list of dictionaries with 2 entries each - :param selected_inputs: values of all checked elements - :type selected_inputs: list of strings :param forward_depth: forward recursion depth :type forward_depth: unsigned int :param backward_depth: backward recursion depth @@ -278,7 +279,15 @@ def generate_output(n_clicks,all_inputs,selected_inputs, elif 'Update Automatically' in additional_options \ or 'start-button' in changed_id: input_links = [x['value'] for x in all_inputs] - Processing(input_links,int(forward_depth),int(backward_depth),'assets/json_text.json') + errors = Processing(input_links,int(forward_depth),int(backward_depth),'assets/json_text.json') + if errors: + message = ['The following inputs are invalid and were not used:'] + for error in errors: + message.append(html.Br()) + message.append(error) + message = html.P(message) + #message = [html.P(error) for error in errors] + return message if __name__ == '__main__': app.run_server(debug=False) diff --git a/input/get/__pycache__/__init__.cpython-38.pyc b/input/get/__pycache__/__init__.cpython-38.pyc index f12fb9c33e874aa1c55d94725f867ac6503d407e..52f5d64aa3f72e25accf523fb850635617afbf5e 100644 Binary files a/input/get/__pycache__/__init__.cpython-38.pyc and b/input/get/__pycache__/__init__.cpython-38.pyc differ diff --git a/input/get/__pycache__/acs.cpython-38.pyc b/input/get/__pycache__/acs.cpython-38.pyc index 121d1856184f02775d5bb84d081dcd91a648ea67..78c1fb0c8b885e90285224e745b09af56faf9b01 100644 Binary files a/input/get/__pycache__/acs.cpython-38.pyc and b/input/get/__pycache__/acs.cpython-38.pyc differ diff --git a/input/get/__pycache__/journal_fetcher.cpython-38.pyc b/input/get/__pycache__/journal_fetcher.cpython-38.pyc index 72a774c45762b3d4cb37a7089f4d8275dab0e533..af9bd12b47a0bae4c1683adf78d92884b7e51193 100644 Binary files a/input/get/__pycache__/journal_fetcher.cpython-38.pyc and b/input/get/__pycache__/journal_fetcher.cpython-38.pyc differ diff --git a/input/get/__pycache__/nature.cpython-38.pyc b/input/get/__pycache__/nature.cpython-38.pyc index 3afb8454a05c8afe9b1f2aba3f534d66cbd8ae3a..ca8c9862b7234c55e49b676136ab64a62f91e58b 100644 Binary files a/input/get/__pycache__/nature.cpython-38.pyc and b/input/get/__pycache__/nature.cpython-38.pyc differ