ricgraph 3.2__tar.gz → 3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ricgraph
3
- Version: 3.2
3
+ Version: 3.3
4
4
  Summary: Ricgraph - Research in context graph
5
5
  Author: Rik D.T. Janssen
6
6
  License-Expression: MIT
@@ -23,7 +23,9 @@ We use color=#4c1 (green), that color is used by the 'repo status' badge.
23
23
  Documentation about the Podman badges can be found here: https://github.com/eggplants/ghcr-badge.
24
24
  --->
25
25
 
26
- > Read the [Tutorial](docs/ricgraph_tutorial.md#tutorial-ricgraph---research-in-context-graph).
26
+ > [Use Ricgraph](https://www.ricgraph.eu/pilot-project-open-ricgraph-demo-server.html).
27
+ > [Read news about Ricgraph](https://www.ricgraph.eu/ricgraph-news.html).
28
+ > Read the [Tutorial](https://docs.ricgraph.eu/docs/ricgraph_tutorial.html).
27
29
  > Go to the [Documentation website](https://docs.ricgraph.eu).
28
30
  > Consult the [Table of contents](docs/ricgraph_toc_documentation.md#table-of-contents-ricgraph-documentation),
29
31
  > or the [Index](docs/ricgraph_index_documentation.md#index-ricgraph-documentation).
@@ -84,58 +86,6 @@ extensive one (also including the use cases).
84
86
  </tr>
85
87
  </table>
86
88
 
87
- ## Ricgraph news
88
-
89
- Read my recent preprint:
90
-
91
- * Rik D.T. Janssen (2025).
92
- *Utilizing Ricgraph to gain insights into research collaborations across institutions,
93
- at every organizational level*. Submitted to SoftwareX [preprint].
94
- [https://doi.org/10.2139/ssrn.5524439](https://doi.org/10.2139/ssrn.5524439).
95
-
96
- See Ricgraph in action:
97
-
98
- * Use the Open Ricgraph demo server
99
- via [https://explorer.ricgraph.eu](https://explorer.ricgraph.eu).
100
- Read more (and join) at
101
- [pilot project Open Ricgraph demo
102
- server](https://www.ricgraph.eu/pilot-project-open-ricgraph-demo-server.html).
103
-
104
-
105
- Currently, there are people working on the following extensions for Ricgraph:
106
-
107
- * [BackToPure](https://github.com/UtrechtUniversity/backtopure)
108
- is a tool designed to enhance an organization's
109
- [Research Information System Pure](https://www.elsevier.com/solutions/pure)
110
- by enriching its content. BackToPure can identify items
111
- (such as publications, data sets or software)
112
- that exist in other external sources but are missing from the organization's Pure,
113
- and then insert (enrich) those items into Pure.
114
- The result is a more complete overview of research at that organization.
115
- Status: experimental stage (beta).
116
- * A chatbot that allows you to "talk" to Ricgraph. You can formulate questions in
117
- plain English, such as "Please give me the research results of the Geosciences
118
- faculty of Utrecht University?"
119
- or "With what organizations does that faculty collaborate?".
120
- It uses a local Large Language Model.
121
- Status: planning stage (pre-alpha).
122
- * A project with six students from the University of Applied Sciences, Utrecht, that aims to
123
- [create a general harvester for
124
- Ricgraph](docs/ricgraph_outreach.md#ricgraph-projects-with-students).
125
- It will remove a lot of code duplication in the harvest scripts, and will
126
- make it easier to add new harvest sources.
127
- Status: planning stage (pre-alpha).
128
- * A project with a student from the University of Applied Sciences, Utrecht, that aims to use
129
- [AI and Large Language Models to find topics and visualize large amounts of research
130
- information](docs/ricgraph_outreach.md#ricgraph-projects-with-students).
131
- It assigns *topics* to publications,
132
- data sets, and software. By selecting a number of topics, research results are
133
- grouped, and possibly experts on these topics can be found.
134
- Status: planning stage (pre-alpha).
135
- * A tool that helps Pure administrators to clean up "external organizations" in Pure.
136
- Status: planning stage (pre-alpha).
137
-
138
-
139
89
  ## Motivation
140
90
 
141
91
  Ricgraph is software that is about
@@ -403,7 +353,8 @@ The following figure shows how three persons have contributed to one research ou
403
353
 
404
354
  ### Steps to take if you would like to use Ricgraph
405
355
 
406
- * Use [Ricgraph Explorer](docs/ricgraph_explorer.md#ricgraph-explorer),
356
+ * [Use Ricgraph](https://www.ricgraph.eu/pilot-project-open-ricgraph-demo-server.html).
357
+ * Read more about [Ricgraph Explorer](docs/ricgraph_explorer.md#ricgraph-explorer),
407
358
  the exploration tool for Ricgraph.
408
359
  * Use the [Ricgraph REST API](docs/ricgraph_restapi.md#ricgraph-rest-api),
409
360
  the REST API for Ricgraph.
@@ -449,4 +400,4 @@ please let me know by creating a GitHub *Issue* at the top left of that page.
449
400
  <!-- Do not change the lines below. The version number will be
450
401
  modified by script maintenance/update_version.bash -->
451
402
  This README.md file is part of the
452
- documentation for version 3.2 of Ricgraph - Research in context graph.
403
+ documentation for version 3.3 of Ricgraph - Research in context graph.
@@ -7,7 +7,7 @@ packages = ["ricgraph"]
7
7
 
8
8
  [project]
9
9
  name = "ricgraph"
10
- version = "3.2"
10
+ version = "3.3"
11
11
  authors = [
12
12
  { name="Rik D.T. Janssen" },
13
13
  ]
@@ -90,7 +90,7 @@ In the default configuration of Ricgraph, the following properties are included:
90
90
 
91
91
  - url_other: other URL for a node, pointing to e.g. the originating record in a source system.
92
92
 
93
- - year: year of a research output.
93
+ - year: year of a research result.
94
94
 
95
95
  - source_event: an event to be added to the _source list.
96
96
 
@@ -100,8 +100,8 @@ In the default configuration of Ricgraph, the following properties are included:
100
100
 
101
101
  from numpy import nan
102
102
  from pandas import DataFrame, concat, set_option
103
- from typing import Union
104
103
 
104
+ from .ricgraph_constants import PERSON_CATEGORY_PERSON
105
105
  from .ricgraph_utils import (timestamp, timestamp_posix,
106
106
  print_records_per_minute,
107
107
  print_progress)
@@ -120,7 +120,7 @@ __package__ = 'Ricgraph'
120
120
  # __version__ should be placed here instead of in __init__.py.
121
121
  # If not here, it cannot be found when executing something like
122
122
  # PYTHONPATH=../ricgraph ../bin/python ricgraph_explorer.py
123
- __version__ = '3.2'
123
+ __version__ = '3.3'
124
124
 
125
125
 
126
126
  # ##############################################################################
@@ -164,7 +164,8 @@ def update_nodes_df(nodes: DataFrame) -> None:
164
164
  if prop_name == other_name:
165
165
  node_properties[prop_name] = getattr(row, other_name)
166
166
 
167
- create_update_node(name=row.name, category=row.category, value=row.value,
167
+ create_update_node(name=str(row.name), category=str(row.category),
168
+ value=str(row.value),
168
169
  other_properties=node_properties)
169
170
 
170
171
  print_progress(count=count, now=True)
@@ -175,7 +176,7 @@ def update_nodes_df(nodes: DataFrame) -> None:
175
176
  return
176
177
 
177
178
 
178
- def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame) -> None:
179
+ def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame | None) -> None:
179
180
  """Create two nodes (called 'node pairs') and two directed edges between those nodes.
180
181
  This is done for all the nodes passed. The nodes are specified in a DataFrame.
181
182
  One row in the DataFrame contains two nodes which are to be connected.
@@ -187,6 +188,8 @@ def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame) -> None:
187
188
  :param left_and_right_nodepairs: the node pairs in a DataFrame.
188
189
  :return: None.
189
190
  """
191
+ if left_and_right_nodepairs is None or left_and_right_nodepairs.empty:
192
+ return
190
193
  print('There are ' + str(len(left_and_right_nodepairs)) + ' rows ('
191
194
  + timestamp() + '), creating nodes and edges for row:')
192
195
  count = 0
@@ -203,8 +206,10 @@ def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame) -> None:
203
206
  if prop_name + '2' == other_name:
204
207
  node_properties[prop_name + '2'] = getattr(row, other_name)
205
208
 
206
- create_two_nodes_and_edge(name1=row.name1, category1=row.category1, value1=row.value1,
207
- name2=row.name2, category2=row.category2, value2=row.value2,
209
+ create_two_nodes_and_edge(name1=str(row.name1), category1=str(row.category1),
210
+ value1=str(row.value1),
211
+ name2=str(row.name2), category2=str(row.category2),
212
+ value2=str(row.value2),
208
213
  **node_properties)
209
214
  print_progress(count=count, now=True)
210
215
  end_ts = timestamp_posix()
@@ -214,9 +219,9 @@ def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame) -> None:
214
219
  return
215
220
 
216
221
 
217
- def create_nodepairs_and_edges_params(name1: Union[dict, str], category1: Union[dict, str], value1: Union[dict, str],
218
- name2: Union[dict, str], category2: Union[dict, str], value2: Union[dict, str],
219
- **other_properties: Union[dict, str]) -> None:
222
+ def create_nodepairs_and_edges_params(name1: dict | str, category1: dict | str, value1: dict | str,
223
+ name2: dict | str, category2: dict | str, value2: dict | str,
224
+ **other_properties: dict | str) -> None:
220
225
  """Create two nodes (called 'node pairs') and two directed edges between those nodes.
221
226
  This is done for all the nodes passed. The nodes are specified by values passed to this function.
222
227
  Each value can be either a string or a dict containing strings.
@@ -285,7 +290,7 @@ def create_nodepairs_and_edges_params(name1: Union[dict, str], category1: Union[
285
290
 
286
291
 
287
292
  def unify_personal_identifiers(personal_identifiers: DataFrame,
288
- source_event: Union[dict, str], history_event: Union[dict, str]) -> None:
293
+ source_event: dict | str, history_event: dict | str) -> None:
289
294
  """Unify a collection of personal identifiers (e.g. ORCID, ISNI, etc.).
290
295
  That means that every column is unified to every other column.
291
296
  The identifiers are specified as columns in a DataFrame.
@@ -343,9 +348,9 @@ def unify_personal_identifiers(personal_identifiers: DataFrame,
343
348
  identifiers.rename(columns={column1: 'value1',
344
349
  column2: 'value2'}, inplace=True)
345
350
  new_identifiers_columns = {'name1': column1,
346
- 'category1': 'person',
351
+ 'category1': PERSON_CATEGORY_PERSON,
347
352
  'name2': column2,
348
- 'category2': 'person',
353
+ 'category2': PERSON_CATEGORY_PERSON,
349
354
  'source_event1': source_event,
350
355
  'history_event1': history_event,
351
356
  'source_event2': source_event,
@@ -43,7 +43,7 @@
43
43
 
44
44
 
45
45
  from sys import getsizeof
46
- from typing import Optional
46
+ from typing import Optional, Tuple
47
47
  from pymemcache.client.base import Client
48
48
  from .ricgraph_constants import MAX_NODES_CACHE_KEY_ID
49
49
  from .ricgraph_utils import (get_configfile_key_memcached_parameters,
@@ -126,12 +126,14 @@ def nodes_cache_key_id_create(key: str, elementid: str) -> None:
126
126
  :param elementid: id of a node.
127
127
  :return: None.
128
128
  """
129
- global _nodes_cache_key_id, _memcached_available
129
+ global _nodes_cache_key_id, _memcached_available, _memcached_client
130
130
 
131
131
  if key == '' or elementid == '':
132
132
  return
133
133
 
134
134
  if memcached_check_available():
135
+ if _memcached_client is None:
136
+ return
135
137
  # The docs are unclear whether I need to serialize the key if I
136
138
  # use flag allow_unicode_keys=True in Client() above.
137
139
  # So I do serialize to be sure. Since keys cannot have spaces,
@@ -167,12 +169,14 @@ def nodes_cache_key_id_read(key: str) -> str:
167
169
  :param key: _key of a node.
168
170
  :return: The id of the node, or '' if not present.
169
171
  """
170
- global _nodes_cache_key_id, _memcached_available
172
+ global _nodes_cache_key_id, _memcached_available, _memcached_client
171
173
 
172
174
  if key == '':
173
175
  return ''
174
176
 
175
177
  if memcached_check_available():
178
+ if _memcached_client is None:
179
+ return ''
176
180
  key_serialized = serialize_value(value=key.replace(' ', '_'))
177
181
  try:
178
182
  elementid_serialized = _memcached_client.get(key=key_serialized)
@@ -201,12 +205,14 @@ def nodes_cache_key_id_delete_key(key: str) -> None:
201
205
  :param key: _key of a node.
202
206
  :return: None.
203
207
  """
204
- global _nodes_cache_key_id, _memcached_available
208
+ global _nodes_cache_key_id, _memcached_available, _memcached_client
205
209
 
206
210
  if key == '':
207
211
  return
208
212
 
209
213
  if memcached_check_available():
214
+ if _memcached_client is None:
215
+ return
210
216
  key_serialized = serialize_value(value=key.replace(' ', '_'))
211
217
  try:
212
218
  # Works regardless whether the key is present or not.
@@ -230,9 +236,11 @@ def nodes_cache_key_id_empty() -> None:
230
236
 
231
237
  :return: None.
232
238
  """
233
- global _nodes_cache_key_id, _memcached_available
239
+ global _nodes_cache_key_id, _memcached_available, _memcached_client
234
240
 
235
241
  if memcached_check_available():
242
+ if _memcached_client is None:
243
+ return
236
244
  try:
237
245
  _memcached_client.flush_all()
238
246
  except:
@@ -247,31 +255,45 @@ def nodes_cache_key_id_empty() -> None:
247
255
  return
248
256
 
249
257
 
250
- def nodes_cache_key_id_type_size() -> str:
258
+ def nodes_cache_key_id_size() -> Tuple[int, float]:
251
259
  """Return the size of the cache for node id's.
252
260
  'id' in this sentence is the id assigned by de graph database.
253
261
 
254
- :return: a sentence with the length of the cache and its size.
262
+ :return: a tuple with number of items and size in kB.
255
263
  """
256
- global _nodes_cache_key_id
264
+ global _nodes_cache_key_id, _memcached_client
257
265
 
258
266
  if memcached_check_available():
259
- result = 'Ricgraph uses Memcached as cache. '
267
+ if _memcached_client is None:
268
+ return 0, 0.0
260
269
  try:
261
270
  stats = _memcached_client.stats()
262
- items = int(stats.get(b'curr_items', 0))
271
+ nr_items = int(stats.get(b'curr_items', 0))
263
272
  bytes_used = int(stats.get(b'bytes', 0))
264
273
  size_kb = round(bytes_used / 1000, 1)
265
274
  except:
266
275
  # In case the connection to Memcached is lost, we will also end up here,
267
276
  # and we just continue.
268
- items = 0
277
+ nr_items = 0
269
278
  size_kb = 0.0
270
279
  else:
271
- result = 'Ricgraph uses a local cache. '
272
- items = len(_nodes_cache_key_id)
280
+ nr_items = len(_nodes_cache_key_id)
273
281
  size_kb = round(getsizeof(_nodes_cache_key_id) / 1000, 1)
282
+ return nr_items, size_kb
283
+
284
+
285
+ def nodes_cache_key_id_type_size() -> str:
286
+ """Return the size of the cache for node id's.
287
+ 'id' in this sentence is the id assigned by de graph database.
288
+
289
+ :return: a sentence with the length of the cache and its size.
290
+ """
291
+ nr_items, size_kb = nodes_cache_key_id_size()
292
+ if memcached_check_available():
293
+ result = 'Ricgraph uses Memcached as cache. '
294
+ else:
295
+ result = 'Ricgraph uses a local cache. '
274
296
 
275
- result += 'This cache has ' + str(items) + ' elements, and its size is '
297
+ result += 'This cache has ' + str(nr_items) + ' elements, and its size is '
276
298
  result += str(size_kb) + ' kB.'
277
299
  return result