deduplicate-it 1.2.0__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.
@@ -0,0 +1,152 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship made available under
36
+ the License, as indicated by a copyright notice that is included
37
+ in or attached to the work.
38
+
39
+ "Derivative Works" shall mean any work, whether in Source or Object
40
+ form, that is based on (or derived from) the Work and for which the
41
+ editorial revisions, annotations, elaborations, or other
42
+ transformations represent, as a whole, an original work of authorship.
43
+
44
+ "Contribution" shall mean, as submitted to the Licensor for inclusion
45
+ in the Work by the copyright owner or by an individual or Legal Entity
46
+ authorized to submit on behalf of the copyright owner.
47
+
48
+ "Contributor" shall mean Licensor and any Legal Entity on behalf of
49
+ whom a Contribution has been received by the Licensor and included
50
+ within the Work.
51
+
52
+ 2. Grant of Copyright License. Subject to the terms and conditions of
53
+ this License, each Contributor hereby grants to You a perpetual,
54
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
55
+ copyright license to reproduce, prepare Derivative Works of,
56
+ publicly display, publicly perform, sublicense, and distribute the
57
+ Work and such Derivative Works in Source or Object form.
58
+
59
+ 3. Grant of Patent License. Subject to the terms and conditions of
60
+ this License, each Contributor hereby grants to You a perpetual,
61
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
62
+ (except as stated in this section) patent license to make, have made,
63
+ use, offer to sell, sell, import, and otherwise transfer the Work,
64
+ where such license applies only to those patent contributions
65
+ Licensable by such Contributor that are necessarily infringed by
66
+ their Contribution(s) alone or by the combination of their
67
+ Contribution(s) with the Work to which such Contribution(s) was
68
+ submitted. If You institute patent litigation against any entity
69
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
70
+ the Work or any such patent application constitutes direct or
71
+ contributory patent infringement, then any patent rights granted to
72
+ You under this License for that Work shall terminate as of the date
73
+ such litigation is filed.
74
+
75
+ 4. Redistribution. You may reproduce and distribute copies of the Work
76
+ or Derivative Works thereof in any medium, with or without
77
+ modifications, and in Source or Object form, provided that You meet
78
+ the following conditions:
79
+
80
+ (a) You must give any other recipients of the Work or Derivative Works
81
+ a copy of this License; and
82
+
83
+ (b) You must cause any modified files to carry prominent notices
84
+ stating that You changed the files; and
85
+
86
+ (c) You must retain, in the Source form of any Derivative Works that
87
+ You distribute, all copyright, patent, trademark, and attribution
88
+ notices from the Source form of the Work, excluding those notices
89
+ that do not pertain to any part of the Derivative Works; and
90
+
91
+ (d) If the Work includes a "NOTICE" text file, You must include a
92
+ readable copy of the attribution notices contained within such
93
+ NOTICE file, in at least one of the following places: within a
94
+ NOTICE text provided with the Derivative Works; within the Source
95
+ form or documentation, if provided along with the Derivative Works;
96
+ or, within a display generated by the Derivative Works, if and
97
+ wherever such third-party notices normally appear.
98
+
99
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
100
+ any Contribution intentionally submitted for inclusion in the Work
101
+ by You to the Licensor shall be under the terms and conditions of
102
+ this License, without any additional terms or conditions.
103
+
104
+ 6. Trademarks. This License does not grant permission to use the trade
105
+ names, trademarks, service marks, or product names of the Licensor,
106
+ except as required for reasonable and customary use in describing the
107
+ origin of the Work and reproducing the content of the NOTICE file.
108
+
109
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed
110
+ to in writing, Licensor provides the Work (and each Contributor
111
+ provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES
112
+ OR CONDITIONS OF ANY KIND, either express or implied, including,
113
+ without limitation, any warranties or conditions of TITLE,
114
+ NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
115
+ You are solely responsible for determining the appropriateness of using
116
+ or redistributing the Work and assume any risks associated with Your
117
+ exercise of permissions under this License.
118
+
119
+ 8. Limitation of Liability. In no event and under no legal theory,
120
+ whether in tort (including negligence), contract, or otherwise, unless
121
+ required by applicable law (such as deliberate and grossly negligent
122
+ acts) or agreed to in writing, shall any Contributor be liable to You
123
+ for damages, including any direct, indirect, special, incidental, or
124
+ consequential damages of any character arising as a result of this
125
+ License or out of the use or inability to use the Work.
126
+
127
+ 9. Accepting Warranty or Additional Liability. While redistributing the
128
+ Work or Derivative Works thereof, You may choose to offer, and charge
129
+ a fee for, acceptance of support, warranty, indemnity, or other
130
+ liability obligations and/or rights consistent with this License.
131
+ However, in accepting such obligations, You may act only on Your own
132
+ behalf and on Your sole responsibility, not on behalf of any other
133
+ Contributor, and only if You agree to indemnify, defend, and hold each
134
+ Contributor harmless for any liability incurred by, or claims asserted
135
+ against, such Contributor by reason of your accepting any such warranty
136
+ or additional liability.
137
+
138
+ END OF TERMS AND CONDITIONS
139
+
140
+ Copyright 2025 David Purkarthofer and Sebastian Labenbacher
141
+
142
+ Licensed under the Apache License, Version 2.0 (the "License");
143
+ you may not use this file except in compliance with the License.
144
+ You may obtain a copy of the License at
145
+
146
+ http://www.apache.org/licenses/LICENSE-2.0
147
+
148
+ Unless required by applicable law or agreed to in writing, software
149
+ distributed under the License is distributed on an "AS IS" BASIS,
150
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
151
+ See the License for the specific language governing permissions and
152
+ limitations under the License.
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: deduplicate-it
3
+ Version: 1.2.0
4
+ Summary: Free, auditable removal of duplicate records from literature search exports for systematic reviews, scoping reviews and meta-analyses.
5
+ Author: David Purkarthofer, Sebastian Labenbacher
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://deduplicate.it
8
+ Project-URL: Repository, https://github.com/dpurkarthofer/deduplicate.it
9
+ Project-URL: Paper, https://doi.org/10.1177/18911803261484937
10
+ Project-URL: Archive, https://doi.org/10.5281/zenodo.18835297
11
+ Project-URL: Changelog, https://github.com/dpurkarthofer/deduplicate.it/blob/main/CHANGELOG.md
12
+ Keywords: systematic-review,scoping-review,meta-analysis,deduplication,evidence-synthesis,literature-search,PRISMA,RIS,BibTeX,MEDLINE
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Intended Audience :: Healthcare Industry
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
21
+ Classifier: Topic :: Text Processing :: Filters
22
+ Classifier: Operating System :: OS Independent
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Dynamic: license-file
27
+
28
+ # deduplicate.it
29
+
30
+ Free, open-source tool for automated deduplication of literature search exports for systematic reviews, scoping reviews, and meta-analyses.
31
+
32
+ **Web interface:** [deduplicate.it](https://deduplicate.it)
33
+
34
+ [![Paper](https://img.shields.io/badge/Campbell%20Syst%20Rev-10.1177%2F18911803261484937-1a7f37)](https://doi.org/10.1177/18911803261484937)
35
+ [![Software archive](https://img.shields.io/badge/Zenodo-10.5281%2Fzenodo.18835297-1682d4)](https://doi.org/10.5281/zenodo.18835297)
36
+ [![License](https://img.shields.io/badge/license-Apache--2.0-lightgrey)](LICENSE)
37
+
38
+ **Peer-reviewed and published.** The matching rule, the evaluation and the limitations are described in full in the methods paper:
39
+
40
+ > Purkarthofer D, Labenbacher S, Bornemann-Cimenti H, Landoni G. deduplicate.it: A simple open-source tool to remove duplicates from literature searches. *Campbell Systematic Reviews*. 2026;22(3). doi:[10.1177/18911803261484937](https://doi.org/10.1177/18911803261484937)
41
+
42
+ Across five real-world searches (958–2,408 records) it removed **76.6–89.6%** of the duplicates found by Rayyan-assisted manual deduplication and cut deduplication time by **68.4–86.7%**. Records without a valid DOI, and records whose DOIs collide, are never silently merged: they are retained, exported separately and sorted to the top of the output for manual review.
43
+
44
+ See [Citation](#citation) for when to cite the software archive instead.
45
+
46
+ ## Contents
47
+
48
+ ### `web/` — PHP web application
49
+ Deploy to any PHP 8.x server. Place `index.php`, `legal.php`, and both `.drawio.html` flowchart templates in the same directory.
50
+
51
+ `.user.ini` raises the upload and memory limits the tool needs — PHP's default
52
+ `upload_max_filesize` of 2 MB is smaller than a typical database export. On shared hosting
53
+ running PHP-FPM, keep it beside `index.php`; on other setups apply the equivalent
54
+ directives in `php.ini`.
55
+
56
+ ### `deduplicate_it/` — Python command-line tool
57
+ No external dependencies (Python standard library only). Requires Python 3.11 or newer.
58
+
59
+ **Install:**
60
+
61
+ ```bash
62
+ pip install deduplicate-it
63
+ ```
64
+
65
+ **Usage:**
66
+
67
+ ```bash
68
+ deduplicate-it --source path/to/exports --outdir path/to/results
69
+ ```
70
+
71
+ With no arguments it reads `./source` and writes to the current directory. Other options:
72
+ `--format` (repeatable: `ris`, `csv`, `medline`, `xml`; default `ris`), `--version`, `--help`.
73
+
74
+ Files are auto-detected by format; processed in alphabetical order (sets tie-break priority).
75
+
76
+ **Running from a clone instead of installing:** `python3 cli/literature_deduplication.py` still
77
+ works from a checkout — it is a thin wrapper around the same code. It needs the `deduplicate_it/`
78
+ package beside it, so download the repository (or a release archive), not that one file on its own.
79
+ Before 1.2.0 the script was self-contained; see the note in [CHANGELOG.md](CHANGELOG.md).
80
+
81
+ ## Supported input formats
82
+
83
+ | Format | Extensions |
84
+ |--------|-----------|
85
+ | MEDLINE / PubMed NBIB | `.txt`, `.nbib` |
86
+ | RIS (Embase, Cochrane databases, CINAHL, Scopus, Web of Science) | `.ris`, `.enw` |
87
+ | Web of Science ISI-tagged | `.ciw` |
88
+ | BibTeX | `.bib` |
89
+ | CSV / TSV | `.csv`, `.tsv` |
90
+
91
+ Format is inferred from file content, not file extension. ERIC's MEDLINE-style `.nbib`
92
+ export is recognised from its own tags, so it is handled correctly whatever the file is
93
+ named.
94
+
95
+ ## Output files
96
+
97
+ | File | Description |
98
+ |------|-------------|
99
+ | `deduplicated.ris` | Deduplicated references — import into Rayyan, Covidence, or EndNote |
100
+ | `deduplicated.csv` | Deduplicated references — tabular |
101
+ | `deduplicated.txt` | Deduplicated references — MEDLINE tagged text |
102
+ | `deduplicated.xml` | Deduplicated references — XML |
103
+ | `excluded_duplicates.csv` | Full audit trail: one row per excluded duplicate paired with the retained record |
104
+ | `doi_collisions.csv` | Records with the same DOI but different titles — retained in output, flagged for manual review |
105
+ | `deduplicated_prisma_flowchart.html` | Editable PRISMA-style flowchart, pre-filled with record counts |
106
+ | `deduplicated_prisma_flowchart_extended.html` | As above, with the per-database breakdown |
107
+
108
+ The web application offers all four deduplicated-reference formats for download. The
109
+ command-line tool writes RIS only by default. `--format` **replaces** that default rather than
110
+ adding to it, so name every format you want, RIS included: `--format ris --format csv` writes
111
+ both, while `--format csv` on its own writes no RIS file.
112
+
113
+ ## Algorithm
114
+
115
+ Deduplication uses a compound key of **normalised DOI** and **normalised title**. Records are excluded only when both fields agree after normalisation. Records without a valid DOI, or without a normalised title, pass through unchanged. DOI collisions (same DOI, different titles — common in conference supplement publications) are kept in the output and exported to a separate log for manual review.
116
+
117
+ Where a database publishes no DOI field but stores the DOI inside a link field — ERIC is the
118
+ common case — the DOI is recovered from that link. Candidates must still pass full
119
+ structural validation, so record pages, PDFs and other non-DOI URLs are ignored.
120
+
121
+ See the accompanying manuscript and Supplement A for a full step-by-step technical description.
122
+
123
+ ## Version history
124
+
125
+ See [CHANGELOG.md](CHANGELOG.md). The **release version** (currently 1.2.0) and the
126
+ **algorithm generation** (`v6`) are tracked separately: the algorithm generation changes
127
+ only when deduplication decisions change. The web application and the Python package share
128
+ the release version, so 1.2.0 means the same algorithm in both.
129
+
130
+ ## License
131
+
132
+ Copyright 2025 David Purkarthofer and Sebastian Labenbacher.
133
+ Apache License 2.0 — see [LICENSE](LICENSE).
134
+
135
+ ## Citation
136
+
137
+ **Please cite the methods paper.** This is the citation to use when deduplicate.it
138
+ contributed to a review:
139
+
140
+ > Purkarthofer, D., Labenbacher, S., Bornemann-Cimenti, H., & Landoni, G. (2026).
141
+ > *deduplicate.it: A simple open-source tool to remove duplicates from literature searches.*
142
+ > Campbell Systematic Reviews, 22(3). https://doi.org/10.1177/18911803261484937
143
+
144
+ A `CITATION.cff` file is included, so GitHub's "Cite this repository" button returns the
145
+ reference above.
146
+
147
+ **Citing the software itself** is only needed when you have to point at a specific version
148
+ of the code — for a reproducibility statement, say:
149
+
150
+ > Purkarthofer D, Labenbacher S. *deduplicate.it: Automated deduplication of literature searches* [Software]. Zenodo. https://doi.org/10.5281/zenodo.18835297
151
+
152
+ That DOI covers all versions and always resolves to the most recent one. To pin the exact
153
+ version you used, take its version-specific DOI from the Zenodo record.
@@ -0,0 +1,126 @@
1
+ # deduplicate.it
2
+
3
+ Free, open-source tool for automated deduplication of literature search exports for systematic reviews, scoping reviews, and meta-analyses.
4
+
5
+ **Web interface:** [deduplicate.it](https://deduplicate.it)
6
+
7
+ [![Paper](https://img.shields.io/badge/Campbell%20Syst%20Rev-10.1177%2F18911803261484937-1a7f37)](https://doi.org/10.1177/18911803261484937)
8
+ [![Software archive](https://img.shields.io/badge/Zenodo-10.5281%2Fzenodo.18835297-1682d4)](https://doi.org/10.5281/zenodo.18835297)
9
+ [![License](https://img.shields.io/badge/license-Apache--2.0-lightgrey)](LICENSE)
10
+
11
+ **Peer-reviewed and published.** The matching rule, the evaluation and the limitations are described in full in the methods paper:
12
+
13
+ > Purkarthofer D, Labenbacher S, Bornemann-Cimenti H, Landoni G. deduplicate.it: A simple open-source tool to remove duplicates from literature searches. *Campbell Systematic Reviews*. 2026;22(3). doi:[10.1177/18911803261484937](https://doi.org/10.1177/18911803261484937)
14
+
15
+ Across five real-world searches (958–2,408 records) it removed **76.6–89.6%** of the duplicates found by Rayyan-assisted manual deduplication and cut deduplication time by **68.4–86.7%**. Records without a valid DOI, and records whose DOIs collide, are never silently merged: they are retained, exported separately and sorted to the top of the output for manual review.
16
+
17
+ See [Citation](#citation) for when to cite the software archive instead.
18
+
19
+ ## Contents
20
+
21
+ ### `web/` — PHP web application
22
+ Deploy to any PHP 8.x server. Place `index.php`, `legal.php`, and both `.drawio.html` flowchart templates in the same directory.
23
+
24
+ `.user.ini` raises the upload and memory limits the tool needs — PHP's default
25
+ `upload_max_filesize` of 2 MB is smaller than a typical database export. On shared hosting
26
+ running PHP-FPM, keep it beside `index.php`; on other setups apply the equivalent
27
+ directives in `php.ini`.
28
+
29
+ ### `deduplicate_it/` — Python command-line tool
30
+ No external dependencies (Python standard library only). Requires Python 3.11 or newer.
31
+
32
+ **Install:**
33
+
34
+ ```bash
35
+ pip install deduplicate-it
36
+ ```
37
+
38
+ **Usage:**
39
+
40
+ ```bash
41
+ deduplicate-it --source path/to/exports --outdir path/to/results
42
+ ```
43
+
44
+ With no arguments it reads `./source` and writes to the current directory. Other options:
45
+ `--format` (repeatable: `ris`, `csv`, `medline`, `xml`; default `ris`), `--version`, `--help`.
46
+
47
+ Files are auto-detected by format; processed in alphabetical order (sets tie-break priority).
48
+
49
+ **Running from a clone instead of installing:** `python3 cli/literature_deduplication.py` still
50
+ works from a checkout — it is a thin wrapper around the same code. It needs the `deduplicate_it/`
51
+ package beside it, so download the repository (or a release archive), not that one file on its own.
52
+ Before 1.2.0 the script was self-contained; see the note in [CHANGELOG.md](CHANGELOG.md).
53
+
54
+ ## Supported input formats
55
+
56
+ | Format | Extensions |
57
+ |--------|-----------|
58
+ | MEDLINE / PubMed NBIB | `.txt`, `.nbib` |
59
+ | RIS (Embase, Cochrane databases, CINAHL, Scopus, Web of Science) | `.ris`, `.enw` |
60
+ | Web of Science ISI-tagged | `.ciw` |
61
+ | BibTeX | `.bib` |
62
+ | CSV / TSV | `.csv`, `.tsv` |
63
+
64
+ Format is inferred from file content, not file extension. ERIC's MEDLINE-style `.nbib`
65
+ export is recognised from its own tags, so it is handled correctly whatever the file is
66
+ named.
67
+
68
+ ## Output files
69
+
70
+ | File | Description |
71
+ |------|-------------|
72
+ | `deduplicated.ris` | Deduplicated references — import into Rayyan, Covidence, or EndNote |
73
+ | `deduplicated.csv` | Deduplicated references — tabular |
74
+ | `deduplicated.txt` | Deduplicated references — MEDLINE tagged text |
75
+ | `deduplicated.xml` | Deduplicated references — XML |
76
+ | `excluded_duplicates.csv` | Full audit trail: one row per excluded duplicate paired with the retained record |
77
+ | `doi_collisions.csv` | Records with the same DOI but different titles — retained in output, flagged for manual review |
78
+ | `deduplicated_prisma_flowchart.html` | Editable PRISMA-style flowchart, pre-filled with record counts |
79
+ | `deduplicated_prisma_flowchart_extended.html` | As above, with the per-database breakdown |
80
+
81
+ The web application offers all four deduplicated-reference formats for download. The
82
+ command-line tool writes RIS only by default. `--format` **replaces** that default rather than
83
+ adding to it, so name every format you want, RIS included: `--format ris --format csv` writes
84
+ both, while `--format csv` on its own writes no RIS file.
85
+
86
+ ## Algorithm
87
+
88
+ Deduplication uses a compound key of **normalised DOI** and **normalised title**. Records are excluded only when both fields agree after normalisation. Records without a valid DOI, or without a normalised title, pass through unchanged. DOI collisions (same DOI, different titles — common in conference supplement publications) are kept in the output and exported to a separate log for manual review.
89
+
90
+ Where a database publishes no DOI field but stores the DOI inside a link field — ERIC is the
91
+ common case — the DOI is recovered from that link. Candidates must still pass full
92
+ structural validation, so record pages, PDFs and other non-DOI URLs are ignored.
93
+
94
+ See the accompanying manuscript and Supplement A for a full step-by-step technical description.
95
+
96
+ ## Version history
97
+
98
+ See [CHANGELOG.md](CHANGELOG.md). The **release version** (currently 1.2.0) and the
99
+ **algorithm generation** (`v6`) are tracked separately: the algorithm generation changes
100
+ only when deduplication decisions change. The web application and the Python package share
101
+ the release version, so 1.2.0 means the same algorithm in both.
102
+
103
+ ## License
104
+
105
+ Copyright 2025 David Purkarthofer and Sebastian Labenbacher.
106
+ Apache License 2.0 — see [LICENSE](LICENSE).
107
+
108
+ ## Citation
109
+
110
+ **Please cite the methods paper.** This is the citation to use when deduplicate.it
111
+ contributed to a review:
112
+
113
+ > Purkarthofer, D., Labenbacher, S., Bornemann-Cimenti, H., & Landoni, G. (2026).
114
+ > *deduplicate.it: A simple open-source tool to remove duplicates from literature searches.*
115
+ > Campbell Systematic Reviews, 22(3). https://doi.org/10.1177/18911803261484937
116
+
117
+ A `CITATION.cff` file is included, so GitHub's "Cite this repository" button returns the
118
+ reference above.
119
+
120
+ **Citing the software itself** is only needed when you have to point at a specific version
121
+ of the code — for a reproducibility statement, say:
122
+
123
+ > Purkarthofer D, Labenbacher S. *deduplicate.it: Automated deduplication of literature searches* [Software]. Zenodo. https://doi.org/10.5281/zenodo.18835297
124
+
125
+ That DOI covers all versions and always resolves to the most recent one. To pin the exact
126
+ version you used, take its version-specific DOI from the Zenodo record.
@@ -0,0 +1,11 @@
1
+ """deduplicate.it — remove duplicate records from literature search exports.
2
+
3
+ Release 1.2.0 · algorithm generation v6.
4
+ See CHANGELOG.md for the release history.
5
+ """
6
+
7
+ __version__ = "1.2.0"
8
+
9
+ from .core import main # noqa: E402,F401
10
+
11
+ __all__ = ["main", "__version__"]