ipaapi 1.0.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,11 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .pytest_cache/
7
+ .venv/
8
+ venv/
9
+ .DS_Store
10
+ *.ipynb_checkpoints/
11
+ .ipaapi_token.json
@@ -0,0 +1,345 @@
1
+ # Changelog
2
+
3
+ Versions follow [semantic versioning](https://semver.org): breaking changes to
4
+ the command line or the Python API bump the major number, additions bump the
5
+ minor, fixes bump the patch.
6
+
7
+ Check what you're running with `ipaapi --version`, which reports the version,
8
+ the install location, and whether it's an editable checkout rather than a wheel.
9
+
10
+ ## 1.0.0 — 2026-08-05
11
+
12
+ First stable release. No code changes from 0.5.0 — the version marks that the
13
+ interface is settled and the package has been used in earnest.
14
+
15
+ Established in production: 37 analyses submitted against live IPA across 5
16
+ donors and 9 cell types, with batch submission, quota-aware resume and the
17
+ identifier/measurement vocabulary all exercised.
18
+
19
+ From here, breaking changes to the CLI or the Python API require a major
20
+ version bump.
21
+
22
+ ### Interface considered stable
23
+
24
+ - `ipaapi validate | submit | status | report | history` and their flags.
25
+ - `ColumnMapping`, `Observation`, `Measurement`, `Dataset`, `IPAClient`.
26
+ - `MeasurementType`, `AnalysisStatus`, `ReferenceSet`, `GENE_ID_TYPES`.
27
+ - The exception hierarchy under `IPAError`.
28
+ - The submission log format (tab-separated, header row, append-only).
29
+
30
+ ## 0.5.0 — 2026-08-05
31
+
32
+ ### Changed
33
+
34
+ - **Released under the MIT licence.** `pyproject.toml` previously declared
35
+ `Proprietary` with no `LICENSE` file present — a combination that, on a public
36
+ repository, legally means nobody may use it. Adds `LICENSE`, the OSI
37
+ classifier, and supported-Python classifiers.
38
+ - Package description rewritten to say what the tool does and what distinguishes
39
+ it, and to stop advertising result retrieval, which needs a commercial add-on.
40
+ - README gains Contributing and Licence sections, and a Status section listing
41
+ the known open questions rather than leaving them implicit.
42
+
43
+ ## 0.4.1 — 2026-08-05
44
+
45
+ ### Documentation
46
+
47
+ - **Extended README**, structured as a manual: quick start, full CLI reference,
48
+ recipes, a section on the undocumented parts of IPA, authentication including
49
+ headless use, Python API, troubleshooting table, and the wire format.
50
+ - **Corrected again — the reference-set size rule does not hold in practice.**
51
+ 0.4.0 reported §4.1.3.1's rule (ipkb below 2000 identifiers, dataset at 2000
52
+ or more) as fact. Checked against 37 completed analyses of 1,804–6,245
53
+ identifiers, *all* were scored against "Ingenuity Knowledge Base (Genes
54
+ Only)". The documented rule is therefore not predictive; set
55
+ `--reference-set` explicitly for anything you intend to compare.
56
+
57
+ ## 0.4.0 — 2026-08-05
58
+
59
+ Working from QIAGEN's official *IPA Integration Module (APIs)* documentation
60
+ (April 2026) rather than from inference. Several things we had established by
61
+ trial were confirmed; two were wrong.
62
+
63
+ ### Added
64
+
65
+ - **`GENE_ID_TYPES`** — all 33 documented `geneidtype` values with the database
66
+ each refers to (§3.1), exposed as `ipaapi submit --list-id-types`. A value
67
+ outside the list is warned about, with a near-match suggestion, but still
68
+ sent; IPA remains the authority.
69
+ - **Species is carried by the identifier type**, not a separate parameter:
70
+ `hugo` human, `mousesymeg` mouse, `ratsymeg` rat. There is no species
71
+ argument in the API — an open question now closed.
72
+ - **`ReferenceSet.IPKB`** (`ipkb`), the Ingenuity Knowledge Base.
73
+
74
+ ### Changed
75
+
76
+ - **Corrected: omitting `referenceset` does not mean "use the Knowledge
77
+ Base".** IPA chooses by dataset size — `ipkb` below 2000 identifiers,
78
+ `dataset` at 2000 or more (§4.1.3.1). Large pre-filtered hit lists therefore
79
+ get their own genes as the background even with the parameter omitted. Pass
80
+ `--reference-set ipkb` explicitly to override.
81
+
82
+ ### Notes
83
+
84
+ - The measurement types and ranges this package enforces match §3.1 exactly.
85
+ - §3.1 also states that **out-of-range expression values are silently ignored**
86
+ — "analysis will still proceed without errors or warning diagnostics", with
87
+ offending entries dropped. That makes the range check load-bearing rather
88
+ than pedantic: declaring log2 values as `foldchange` would have silently
89
+ discarded every gene between -1 and 1.
90
+
91
+ ## 0.3.3 — 2026-08-05
92
+
93
+ ### Added
94
+
95
+ - **`examples/probe_geneidtype.py` can now enumerate the accepted gene ID
96
+ vocabulary for free.** IPA has no endpoint that lists it, but the failure
97
+ modes are distinguishable: an unknown type is rejected before any analysis is
98
+ created, while a *valid* type gets as far as creating one and only then hits
99
+ the allowance. So when the account is quota-blocked, every accepted type
100
+ reports itself at no cost. The script detects this automatically — it
101
+ continues past acceptances that were blocked by the allowance, and stops
102
+ immediately if a candidate genuinely creates an analysis, so an account with
103
+ allowance remaining is never drained.
104
+
105
+ ## 0.3.2 — 2026-08-05
106
+
107
+ ### Changed
108
+
109
+ - **The allowance rejection is confirmed**: `Unable to run analysis: Analysis
110
+ limit exceeded`, delivered as an HTML page. Added verbatim to
111
+ `QUOTA_PATTERNS` and documented; the remaining patterns stay as guesses at
112
+ other phrasings.
113
+ - Page chrome ("About QIAGEN Bioinformatics | Contact Us (c)2000-2026 ...") is
114
+ stripped along with the support boilerplate, so the message reads as just
115
+ the reason.
116
+
117
+ ## 0.3.1 — 2026-08-05
118
+
119
+ ### Fixed
120
+
121
+ - **Error pages were truncated exactly where the reason lives.** IPA opens its
122
+ error pages with support boilerplate and puts the actual message last; the
123
+ page text was clipped at 300 characters from the front, so a real failure
124
+ read `Unable to run analysis: Analysis ` and stopped. The boilerplate is now
125
+ stripped and the tail preserved.
126
+ - **"No files were moved" was printed even when files had been moved.** A
127
+ mid-batch failure files everything submitted before it; the message now says
128
+ what actually happened.
129
+ - **"Unable to run analysis" was misreported as a parameter error.** That
130
+ wording means the request reached IPA's analysis logic, so it is not a
131
+ malformed request. New `AnalysisRefusedError` says so, and the run stops and
132
+ leaves the remaining files in place — the right behaviour if the cause is an
133
+ allowance or capacity limit.
134
+ - **A quota message delivered as an HTML page** was classified as a bad
135
+ parameter. Quota detection now runs against the whole body before the HTML
136
+ branch.
137
+
138
+ ## 0.3.0 — 2026-08-05
139
+
140
+ Everything needed for a correct analysis is now established and defaulted.
141
+ Confirmed working end to end against live IPA: `hugo` identifiers, `logratio`
142
+ fold changes, no `referenceset` — producing populated p-values and FDR.
143
+
144
+ ### Changed — breaking
145
+
146
+ - **`referenceset` is no longer sent by default.** QIAGEN's demo sent
147
+ `referenceset=dataset`, and this package inherited it unexamined. That makes
148
+ the background the uploaded genes, which for a pre-filtered hit list is the
149
+ same set as the foreground — leaving the enrichment statistics degenerate:
150
+ z-scores produced, p-values and FDR absent. Omitting the parameter lets IPA
151
+ apply its own default, which is confirmed to produce real statistics.
152
+
153
+ `IPAClient.submit(reference_set=...)` now defaults to `None`, and
154
+ `--reference-set` defaults to `omit`. Pass `dataset` explicitly to restore
155
+ the old behaviour — appropriate only when uploading a complete measured
156
+ transcriptome.
157
+
158
+ ## 0.2.7 — 2026-08-05
159
+
160
+ ### Added
161
+
162
+ - **`hugo` confirmed as a gene ID type** for human gene symbols, verified
163
+ against the live API. `CONFIRMED_ID_TYPES` is now `("ensembl", "hugo")`.
164
+ Of the three names in the desktop client's label "Gene Symbol - human
165
+ (HUGO / HGNC / Entrez Gene)", only the first is accepted — `genesymbol` and
166
+ `Gene Symbol` are both rejected.
167
+ - README documents the confirmed vocabulary, since QIAGEN does not.
168
+
169
+ ## 0.2.6 — 2026-08-05
170
+
171
+ ### Changed
172
+
173
+ - **Rejection messages lead with what was rejected.** The explanation used to
174
+ come first and the actual cause several lines down, which is easy to skim
175
+ past and read as success. The first line is now
176
+ `REJECTED: IPA does not recognise the gene ID type 'X'.`, followed by
177
+ `NOTHING WAS SUBMITTED.`, with the reasoning below that.
178
+ - Recorded that `Gene Symbol` is rejected as well as `genesymbol` — so the API
179
+ does not take the desktop client's display label either.
180
+
181
+ ## 0.2.5 — 2026-08-05
182
+
183
+ ### Changed
184
+
185
+ - Gene ID type candidates reordered from evidence rather than convention. The
186
+ IPA desktop client labels a gene symbol column "Gene Symbol - human (HUGO /
187
+ HGNC / Entrez Gene)", so `symbol`, `hugo`, `hgnc` and `entrezgene` are tried
188
+ first. Still guesses — the client and the REST API need not share vocabulary
189
+ — but guesses taken from IPA's own wording.
190
+
191
+ ## 0.2.4 — 2026-08-05
192
+
193
+ ### Fixed
194
+
195
+ - **Stopped advertising unverified gene ID types.** The help text listed nine
196
+ "common" identifier types that were guesses. `genesymbol` is among the ones
197
+ IPA rejects — "Unknown GeneId Type (genesymbol)" — so the list sent users
198
+ straight into a failed submission. Only `ensembl` is confirmed, and
199
+ `CONFIRMED_ID_TYPES` now holds only values observed to work.
200
+
201
+ ### Added
202
+
203
+ - **An unrecognised gene ID type is named and explained.** IPA identifies the
204
+ value it rejected in its error page; the message now quotes it, points at the
205
+ `--ID` flag specifically rather than offering a list of suspects, and notes
206
+ that probing costs allowance whenever a candidate is *accepted*.
207
+ - `examples/probe_geneidtype.py` tries candidate type strings against a
208
+ two-row extract and stops at the first IPA accepts.
209
+
210
+ ## 0.2.3 — 2026-08-05
211
+
212
+ ### Fixed
213
+
214
+ - **A mapping that fails every file no longer quarantines the directory.** If
215
+ no file validates, the fault is the command rather than the data, so nothing
216
+ is moved to `failed/` and the run says so. Files only get filed when *some*
217
+ succeed and others don't.
218
+
219
+ ### Added
220
+
221
+ - **Fold-change rejections suggest `logratio` when the data is log-scaled.**
222
+ A column named "Fold_change" may hold either linear ratios or log2 values.
223
+ When values declared `foldchange` cluster inside (-1, 1) — where fold change
224
+ cannot go but a log ratio spends most of its time — the error now names
225
+ `logratio` as the likely fix instead of only reporting the rejection.
226
+
227
+ ## 0.2.2 — 2026-08-05
228
+
229
+ ### Added
230
+
231
+ - **Warns when a column declared `logratio` looks like signed fold change.**
232
+ A real log ratio is centred on zero, so its distribution always contains
233
+ values between -1 and 1. Signed fold change (`ratio` if >= 1, else
234
+ `-1/ratio`) can contain none, by construction. A `logratio` column with
235
+ nothing in that interval is therefore almost certainly fold change
236
+ mislabelled — which IPA reads as `2^value`, inflating every magnitude while
237
+ leaving directions intact. Warning only, and skipped below 50 values.
238
+
239
+ ## 0.2.1 — 2026-08-05
240
+
241
+ ### Fixed
242
+
243
+ - **A rejected parameter no longer quarantines good files.** IPA answers a
244
+ malformed request with an HTML error page; that was being treated as a
245
+ per-file failure, so a bad `--reference-set` moved a perfectly good file into
246
+ `failed/`. An HTML response is now `MalformedRequestError`: the run stops, no
247
+ file is moved, and the message names the likely parameters and quotes what
248
+ the page said.
249
+ - Identifier warnings were printed twice per dataset.
250
+
251
+ ### Changed
252
+
253
+ - **Removed `--reference-set ingenuity`.** It was a guess and IPA rejects it.
254
+ - **Added `--reference-set omit`**, which leaves the parameter out of the
255
+ request entirely so IPA applies its own default. For pre-filtered hit lists
256
+ `dataset` makes the background equal the analysis-ready set, which degenerates
257
+ the enrichment statistics — z-scores are still produced but overlap p-values
258
+ are not meaningful.
259
+ - Interpret-link failures report the URL, the response body and the JSON keys
260
+ rather than just the status code.
261
+
262
+ ## 0.2.0 — 2026-08-05
263
+
264
+ First version used against live IPA. Everything below came out of that run.
265
+
266
+ ### Added
267
+
268
+ - **Command line.** `ipaapi` console script with `validate`, `submit`,
269
+ `status`, `report` and `history` subcommands.
270
+ - `--ID COLUMN:TYPE` and `--FC COLUMN:TYPE[:CUTOFF]`, column positions 0-based.
271
+ - `--ID` may be given twice: the second identifier fills rows where the
272
+ primary is blank.
273
+ - **Batch submission.** `PATH` may be a directory; `--pattern` selects files by
274
+ substring or glob, `--recursive` descends. One dataset and analysis per file.
275
+ - **File triage.** Directory submits move each file as its outcome is known:
276
+ `submitted/` when IPA accepts it, `failed/` (with a `.error.txt` note) when
277
+ the file is at fault, left in place when the allowance is exhausted. Those
278
+ folders are excluded from discovery, so a re-run resumes exactly where it
279
+ stopped.
280
+ - **Quota detection.** `QuotaExceededError`, raised on HTTP 429 or when the
281
+ response matches `client.QUOTA_PATTERNS`, so an exhausted allowance is not
282
+ mistaken for a broken file. Heuristic — IPA's wording is undocumented, and
283
+ the raw response body is always reported.
284
+ - **Submission log.** Every analysis appends a timestamped row to
285
+ `~/.local/state/ipaapi/submissions.tsv`; `ipaapi history` reads it back with
286
+ `--project`, `--since`, `--limit` and `--status`. IPA's API cannot enumerate
287
+ analyses, so without this a lost terminal means a lost ID.
288
+ - **Token refresh.** An expired cached token is renewed from its refresh token
289
+ over HTTP, with no browser and no prompt. Makes headless and copied-token
290
+ workflows self-sustaining. `--token-file` points at a cache copied from
291
+ another machine.
292
+ - `IPAAPI_TOKEN_FILE` and `IPAAPI_LOG_FILE` environment variables, for hosts
293
+ where the home directory isn't writable. An unwritable token cache means a
294
+ fresh login on every run, so both failures now say how to fix them.
295
+ - `--skip-rows N` for files with a comment or title line above the header.
296
+ - `--browser NAME`, and a login failure message that distinguishes `DISPLAY`
297
+ unset from no browser found, pointing at `ssh -X` or a port forward.
298
+
299
+ ### Changed
300
+
301
+ - **`submit` no longer waits by default.** It returns once the analyses are
302
+ queued and prints the `status`/`report` commands; `--wait` restores polling.
303
+ `--no-wait` is still accepted so existing commands keep working.
304
+ - Observation and dataset names come from the filename rather than the
305
+ fold-change column header, so a batch doesn't produce analyses all named
306
+ "log2FC".
307
+ - Directory submits validate per file; a malformed file goes to `failed/`
308
+ instead of aborting the batch. `validate` remains all-or-nothing.
309
+
310
+ ### Fixed
311
+
312
+ - **Delimiter sniffing read line 1 rather than the header**, so a comment line
313
+ containing commas caused the whole file to be parsed as CSV — silently, with
314
+ the comment becoming the column names. A header that looks like a comment is
315
+ now rejected with an explanation.
316
+ - **`report` on an unfinished analysis** reported a bare HTTP 500. It now
317
+ checks status first and says the analysis is still running.
318
+ - **Token cache write failures were swallowed**, which looked identical to a
319
+ token expiring instantly.
320
+
321
+ ## 0.1.0 — 2026-08-05
322
+
323
+ Initial package, built on QIAGEN's `python-api-demo` example code.
324
+
325
+ ### Added
326
+
327
+ - `ColumnMapping` / `Observation` / `Measurement`: columns addressed by name in
328
+ any order, validated against the data before upload, replacing the demo's
329
+ fixed positional layout. `ColumnMapping.from_blocks()` reproduces the old
330
+ behaviour for migration.
331
+ - `IPAClient` with `submit`, `status`, `wait_for`, `results` and `report_url`.
332
+ - OAuth 2.0 + PKCE login with a disk token cache.
333
+ - Typed exception hierarchy under `IPAError`.
334
+
335
+ ### Fixed relative to the demo
336
+
337
+ - **Request bodies are percent-encoded.** The demo concatenated them by hand,
338
+ so any value containing a space, `&`, `=`, `+` or `%` corrupted the request —
339
+ including the `Group Max Intensity` column in the demo's own sample dataset.
340
+ - OAuth no longer spins a CPU core waiting for the callback, validates the
341
+ `state` parameter, times out, shuts its server down, and handles an error
342
+ redirect instead of waiting forever.
343
+ - Submissions are never retried automatically, since a retried POST could
344
+ create duplicate analyses. GETs retry with backoff.
345
+ - Access tokens are excluded from `repr()`.
ipaapi-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ken Jones
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.