sparclclient 1.2.1.dev6__py2.py3-none-any.whl → 1.2.2__py2.py3-none-any.whl

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,2054 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "tags": []
7
+ },
8
+ "source": [
9
+ "# SPARCLCLIENT Example Usage"
10
+ ]
11
+ },
12
+ {
13
+ "cell_type": "code",
14
+ "execution_count": 1,
15
+ "metadata": {
16
+ "tags": []
17
+ },
18
+ "outputs": [],
19
+ "source": [
20
+ "__author__ = 'Steve Pothier <steve.pothier@noirlab.edu>'\n",
21
+ "__version__ = '20240306' # yyyymmdd; \n",
22
+ "__keywords__ = ['HowTo', 'astronomy', 'tutorial', 'client', 'sparcl', 'NOIRlab']"
23
+ ]
24
+ },
25
+ {
26
+ "cell_type": "markdown",
27
+ "metadata": {
28
+ "tags": []
29
+ },
30
+ "source": [
31
+ "## Table of contents\n",
32
+ "* [Goals & Summary](#goals)\n",
33
+ "* [Imports and setup](#imports)\n",
34
+ "* [Install SPARCLCLIENT](#install)\n",
35
+ "* [Prepare to use sparcl](#prepare)\n",
36
+ "* [Get general info from SPARCL](#info)\n",
37
+ "* [Get Metadata and Spectra](#get)"
38
+ ]
39
+ },
40
+ {
41
+ "cell_type": "markdown",
42
+ "metadata": {
43
+ "tags": []
44
+ },
45
+ "source": [
46
+ "<a class=\"anchor\" id=\"goals\"></a>\n",
47
+ "## Goals & Summary \n",
48
+ "Demonstrate the use of the `sparclclient` package to get metadata and spectra data from the [NOIRLab SPARCL Server](https://astrosparcl.datalab.noirlab.edu/). Show how to get non-public data if you have authorized credentials.\n",
49
+ "- Discovery: Search for matching metadata and return metadata records.\n",
50
+ "- Retrieve spectra"
51
+ ]
52
+ },
53
+ {
54
+ "cell_type": "markdown",
55
+ "metadata": {
56
+ "tags": []
57
+ },
58
+ "source": [
59
+ "<a class=\"anchor\" id=\"imports\"></a>\n",
60
+ "## Imports and Setup"
61
+ ]
62
+ },
63
+ {
64
+ "cell_type": "code",
65
+ "execution_count": 2,
66
+ "metadata": {
67
+ "tags": []
68
+ },
69
+ "outputs": [],
70
+ "source": [
71
+ "from pprint import pformat as pf\n",
72
+ "from pprint import pp\n",
73
+ "import os.path\n",
74
+ "from importlib import reload\n",
75
+ "from collections import defaultdict\n",
76
+ "from datetime import datetime\n",
77
+ "import warnings\n",
78
+ "from getpass import getpass\n",
79
+ "\n",
80
+ "import matplotlib.pyplot as plt\n",
81
+ "import numpy as np\n",
82
+ "import pandas as pd\n",
83
+ "from IPython.display import display, Markdown, Latex\n",
84
+ "\n",
85
+ "class StopExecution(Exception):\n",
86
+ " def _render_traceback_(self):\n",
87
+ " pass\n",
88
+ "\n",
89
+ "# %matplotlib inline\n",
90
+ "# requires installing ipympl\n",
91
+ "%matplotlib widget\n",
92
+ "plt.rcParams['font.size'] = 14"
93
+ ]
94
+ },
95
+ {
96
+ "cell_type": "raw",
97
+ "metadata": {},
98
+ "source": [
99
+ "### "
100
+ ]
101
+ },
102
+ {
103
+ "cell_type": "markdown",
104
+ "metadata": {
105
+ "tags": []
106
+ },
107
+ "source": [
108
+ "<a class=\"anchor\" id=\"install\"></a>\n",
109
+ "## Install most recent version of the SPARCLCLIENT\n",
110
+ "*NOTE: After installing the most recent version, please restart your kernel.*"
111
+ ]
112
+ },
113
+ {
114
+ "cell_type": "code",
115
+ "execution_count": 3,
116
+ "metadata": {
117
+ "tags": []
118
+ },
119
+ "outputs": [
120
+ {
121
+ "name": "stdout",
122
+ "output_type": "stream",
123
+ "text": [
124
+ "Processing /home/pothiers/sandbox/sparclclient\n",
125
+ " Installing build dependencies ... \u001b[?25ldone\n",
126
+ "\u001b[?25h Getting requirements to build wheel ... \u001b[?25ldone\n",
127
+ "\u001b[?25h Preparing metadata (pyproject.toml) ... \u001b[?25ldone\n",
128
+ "\u001b[?25hBuilding wheels for collected packages: sparclclient\n",
129
+ " Building wheel for sparclclient (pyproject.toml) ... \u001b[?25ldone\n",
130
+ "\u001b[?25h Created wheel for sparclclient: filename=sparclclient-1.2.2b8-py2.py3-none-any.whl size=3533665 sha256=fc035800e3269eccc70d3658f293c93d2fe7f07850a17cbdb47c9b2ce0de36ad\n",
131
+ " Stored in directory: /tmp/pip-ephem-wheel-cache-lko1mvqq/wheels/9b/de/a2/3f7a82cf4ca7c9e775a1ed1daeea35010570464a1aaa8c370c\n",
132
+ "Successfully built sparclclient\n",
133
+ "Installing collected packages: sparclclient\n",
134
+ " Attempting uninstall: sparclclient\n",
135
+ " Found existing installation: sparclclient 1.2.2b8\n",
136
+ " Uninstalling sparclclient-1.2.2b8:\n",
137
+ " Successfully uninstalled sparclclient-1.2.2b8\n",
138
+ "Successfully installed sparclclient-1.2.2b8\n"
139
+ ]
140
+ }
141
+ ],
142
+ "source": [
143
+ "# !pip install --upgrade sparclclient # Latest released version\n",
144
+ "# !pip install --pre --upgrade sparclclient # Lastest pre-released version\n",
145
+ "\n",
146
+ "# Uncomment next line to load SPARCLCLIENT from local current version of software.\n",
147
+ "!pip install --pre --upgrade ../.."
148
+ ]
149
+ },
150
+ {
151
+ "cell_type": "code",
152
+ "execution_count": 4,
153
+ "metadata": {
154
+ "tags": []
155
+ },
156
+ "outputs": [
157
+ {
158
+ "name": "stdout",
159
+ "output_type": "stream",
160
+ "text": [
161
+ "Run started: 2024-05-02 10:22:12.795845\n"
162
+ ]
163
+ }
164
+ ],
165
+ "source": [
166
+ "import sparcl.client\n",
167
+ "print(f'Run started: {str(datetime.now())}')"
168
+ ]
169
+ },
170
+ {
171
+ "cell_type": "markdown",
172
+ "metadata": {
173
+ "editable": true,
174
+ "slideshow": {
175
+ "slide_type": ""
176
+ },
177
+ "tags": []
178
+ },
179
+ "source": [
180
+ "<a class=\"anchor\" id=\"prepare\"></a>\n",
181
+ "# Configure SPARCLCLIENT"
182
+ ]
183
+ },
184
+ {
185
+ "cell_type": "code",
186
+ "execution_count": 5,
187
+ "metadata": {
188
+ "scrolled": true,
189
+ "tags": []
190
+ },
191
+ "outputs": [
192
+ {
193
+ "name": "stdin",
194
+ "output_type": "stream",
195
+ "text": [
196
+ " ········\n"
197
+ ]
198
+ }
199
+ ],
200
+ "source": [
201
+ "# How much output to we want to show?\n",
202
+ "show_help = False # HELP for client functions\n",
203
+ "show_curl = True # Show the underlying SPARCL Server API call\n",
204
+ "verbose = True\n",
205
+ "\n",
206
+ "server = 'https://astrosparcl.datalab.noirlab.edu' # Public Server\n",
207
+ "server = 'https://sparc1.datalab.noirlab.edu' # internal TEST Server\n",
208
+ "server = 'http://localhost:8050' # internal DEV Server\n",
209
+ "\n",
210
+ "priv_dr = 'SDSS-DR17-test'\n",
211
+ "pub_dr = 'BOSS-DR16'\n",
212
+ "\n",
213
+ "# Authenticated Users that are never authorized for anything important.\n",
214
+ "# These are authenticated on both Public and Test SSO servers.\n",
215
+ "auth_user = 'test_user_1@noirlab.edu'\n",
216
+ "unauth_user = 'test_user_2@noirlab.edu'\n",
217
+ "non_user = 'test_user_3@noirlab.edu'\n",
218
+ "usrpw = getpass()"
219
+ ]
220
+ },
221
+ {
222
+ "cell_type": "code",
223
+ "execution_count": 6,
224
+ "metadata": {
225
+ "scrolled": true,
226
+ "tags": []
227
+ },
228
+ "outputs": [
229
+ {
230
+ "name": "stdout",
231
+ "output_type": "stream",
232
+ "text": [
233
+ "apiurl=http://localhost:8050/sparc\n",
234
+ "client=(sparclclient:1.2.2b8, api:11.0, http://localhost:8050/sparc, client_hash=f7bd410278bee26a425387c598dd47e80a8fcdcb, verbose=True, connect_timeout=1.1, read_timeout=5400.0)\n"
235
+ ]
236
+ }
237
+ ],
238
+ "source": [
239
+ "if show_help:\n",
240
+ " help(sparcl.client.SparclClient)\n",
241
+ "client = sparcl.client.SparclClient(url=server, show_curl=show_curl, verbose=verbose)\n",
242
+ "print(f'{client=}')"
243
+ ]
244
+ },
245
+ {
246
+ "cell_type": "markdown",
247
+ "metadata": {},
248
+ "source": [
249
+ "<a class=\"anchor\" id=\"info\"></a>\n",
250
+ "# General Info from SPARCL"
251
+ ]
252
+ },
253
+ {
254
+ "cell_type": "markdown",
255
+ "metadata": {},
256
+ "source": [
257
+ "<a class=\"anchor\" id=\"datasets\"></a>\n",
258
+ "## Data sets available\n",
259
+ "List all currently available data sets from the server/url associated with client"
260
+ ]
261
+ },
262
+ {
263
+ "cell_type": "code",
264
+ "execution_count": 7,
265
+ "metadata": {
266
+ "tags": []
267
+ },
268
+ "outputs": [
269
+ {
270
+ "data": {
271
+ "text/plain": [
272
+ "{'BOSS-DR16', 'DESI-EDR', 'SDSS-DR16', 'SDSS-DR17-test'}"
273
+ ]
274
+ },
275
+ "execution_count": 7,
276
+ "metadata": {},
277
+ "output_type": "execute_result"
278
+ }
279
+ ],
280
+ "source": [
281
+ "client.all_datasets"
282
+ ]
283
+ },
284
+ {
285
+ "cell_type": "markdown",
286
+ "metadata": {},
287
+ "source": [
288
+ "<a class=\"anchor\" id=\"defaultfieldnames\"></a>\n",
289
+ "## Default field names\n",
290
+ "Gets fields tagged as 'default' that are common to all data sets in the `dataset_list` passed to the function. If `dataset_list` is None (the default), the function returns the intersection of 'default' fields across all datasets currently available in the SPARC database. The following example of this function produces the same output as it would with no `dataset_list` argument because we currently only have SDSS-DR16 and BOSS-DR16 records in the SPARC database."
291
+ ]
292
+ },
293
+ {
294
+ "cell_type": "code",
295
+ "execution_count": 8,
296
+ "metadata": {
297
+ "scrolled": true,
298
+ "tags": []
299
+ },
300
+ "outputs": [],
301
+ "source": [
302
+ "if show_help:\n",
303
+ " client.get_default_fields?"
304
+ ]
305
+ },
306
+ {
307
+ "cell_type": "code",
308
+ "execution_count": 9,
309
+ "metadata": {
310
+ "tags": []
311
+ },
312
+ "outputs": [
313
+ {
314
+ "data": {
315
+ "text/plain": [
316
+ "['dec', 'flux', 'ra', 'sparcl_id', 'specid', 'wavelength']"
317
+ ]
318
+ },
319
+ "execution_count": 9,
320
+ "metadata": {},
321
+ "output_type": "execute_result"
322
+ }
323
+ ],
324
+ "source": [
325
+ "client.get_default_fields(dataset_list=['SDSS-DR16', 'BOSS-DR16'])"
326
+ ]
327
+ },
328
+ {
329
+ "cell_type": "markdown",
330
+ "metadata": {},
331
+ "source": [
332
+ "<a class=\"anchor\" id=\"allfieldnames\"></a>\n",
333
+ "## All field names\n",
334
+ "Gets fields tagged as 'all' that are common to all data sets in the `dataset_list` passed to the function. If `dataset_list` is None (the default), the function returns the intersection of 'all' fields across all datasets currently available in the SPARC database. The following example of this function produces the same output as it would with no `dataset_list` argument because we currently only have SDSS-DR16 and BOSS-DR16 records in the SPARC database."
335
+ ]
336
+ },
337
+ {
338
+ "cell_type": "code",
339
+ "execution_count": 10,
340
+ "metadata": {
341
+ "tags": []
342
+ },
343
+ "outputs": [
344
+ {
345
+ "data": {
346
+ "text/plain": [
347
+ "\u001b[0;31mSignature:\u001b[0m \u001b[0mclient\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_all_fields\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdataset_list\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
348
+ "\u001b[0;31mDocstring:\u001b[0m\n",
349
+ "Get fields tagged as 'all' that are in DATASET_LIST.\n",
350
+ "These are the fields used for the ALL value of the include parameter\n",
351
+ "of client.retrieve().\n",
352
+ "\n",
353
+ "Args:\n",
354
+ " dataset_list (:obj:`list`, optional): List of data sets from\n",
355
+ " which to get all fields. Defaults to None, which\n",
356
+ " will return the intersection of all fields in all\n",
357
+ " data sets hosted on the SPARCL database.\n",
358
+ "\n",
359
+ "Returns:\n",
360
+ " List of fields tagged as 'all' from DATASET_LIST.\n",
361
+ "\n",
362
+ "Example:\n",
363
+ " >>> client = SparclClient()\n",
364
+ " >>> client.get_all_fields()\n",
365
+ " ['data_release', 'datasetgroup', 'dateobs', 'dateobs_center', 'dec', 'exptime', 'flux', 'instrument', 'ivar', 'mask', 'model', 'ra', 'redshift', 'redshift_err', 'redshift_warning', 'site', 'sparcl_id', 'specid', 'specprimary', 'spectype', 'survey', 'targetid', 'telescope', 'wave_sigma', 'wavelength', 'wavemax', 'wavemin']\n",
366
+ "\u001b[0;31mFile:\u001b[0m ~/sandbox/sparclclient/venv/lib/python3.10/site-packages/sparcl/client.py\n",
367
+ "\u001b[0;31mType:\u001b[0m method"
368
+ ]
369
+ },
370
+ "metadata": {},
371
+ "output_type": "display_data"
372
+ }
373
+ ],
374
+ "source": [
375
+ "client.get_all_fields?"
376
+ ]
377
+ },
378
+ {
379
+ "cell_type": "code",
380
+ "execution_count": 11,
381
+ "metadata": {
382
+ "tags": []
383
+ },
384
+ "outputs": [
385
+ {
386
+ "name": "stdout",
387
+ "output_type": "stream",
388
+ "text": [
389
+ "['ancillary_target1', 'ancillary_target2', 'anyandmask', 'anyormask', 'bluefiber', 'boss_specobj_id', 'boss_target1', 'boss_target2', 'calibflux', 'calibflux_ivar', 'chi68p', 'chunk', 'class_noqso', 'class_person', 'comments_person', 'cx', 'cy', 'cz', 'data_release', 'datasetgroup', 'dateobs', 'dateobs_center', 'dec', 'deredsn2', 'designid', 'dof', 'eboss_target0', 'eboss_target1', 'eboss_target2', 'eboss_target_id', 'elodie_bv', 'elodie_dof', 'elodie_feh', 'elodie_filename', 'elodie_logg', 'elodie_object', 'elodie_rchi2', 'elodie_sptype', 'elodie_teff', 'elodie_z', 'elodie_z_err', 'elodie_z_modelerr', 'exptime', 'fiberid', 'firstrelease', 'flux', 'fluxobjid', 'fracnsighi', 'fracnsiglo', 'fracnsigma', 'instrument', 'ivar', 'lambda_eff', 'legacy_target1', 'legacy_target2', 'marvels_target1', 'marvels_target2', 'mask', 'mjd', 'model', 'npoly', 'nspecobs', 'nturnoff', 'objid', 'plate', 'plateid', 'platequality', 'platerun', 'platesn2', 'primtarget', 'programname', 'ra', 'rchi2', 'rchi2diff', 'rchi2diff_noqso', 'redshift', 'redshift_err', 'redshift_warning', 'run1d', 'run2d', 'sectarget', 'segue1_target1', 'segue1_target2', 'segue2_target1', 'segue2_target2', 'site', 'sky', 'sn_median', 'sn_median_all', 'snturnoff', 'sourcetype', 'sparcl_id', 'spec1_g', 'spec1_i', 'spec1_r', 'spec2_g', 'spec2_i', 'spec2_r', 'specboss', 'special_target1', 'special_target2', 'specid', 'speclegacy', 'specprimary', 'specsdss', 'specsegue', 'specsegue1', 'specsegue2', 'spectroflux', 'spectroflux_ivar', 'spectrographid', 'spectroskyflux', 'spectrosynflux', 'spectrosynflux_ivar', 'spectype', 'subclass', 'subclass_noqso', 'survey', 'targetid', 'targetobjid', 'targettype', 'tcolumn', 'telescope', 'tfile', 'theta', 'thing_id', 'thing_id_targeting', 'tile', 'vdisp', 'vdisp_err', 'vdispchi2', 'vdispdof', 'vdispnpix', 'vdispz', 'vdispz_err', 'wave_sigma', 'wavelength', 'wavemax', 'wavemin', 'wcoverage', 'xfocal', 'yfocal', 'z_conf_person', 'z_err_noqso', 'z_noqso', 'z_person', 'zoffset', 'zwarning_noqso']\n"
390
+ ]
391
+ }
392
+ ],
393
+ "source": [
394
+ "print(sorted(client.get_all_fields(dataset_list=['SDSS-DR16', 'BOSS-DR16'])))"
395
+ ]
396
+ },
397
+ {
398
+ "cell_type": "markdown",
399
+ "metadata": {},
400
+ "source": [
401
+ "## Version of Server API used by this client\n",
402
+ "The SPARCL Client you use must match the version of the SPARCL Server you use. The server is specified with the client.SparclClient `url` parameter. If Server and Client are incompatible, when you excecute SparclClient() you will instructed to upgrade your client."
403
+ ]
404
+ },
405
+ {
406
+ "cell_type": "code",
407
+ "execution_count": 12,
408
+ "metadata": {
409
+ "tags": []
410
+ },
411
+ "outputs": [
412
+ {
413
+ "data": {
414
+ "text/plain": [
415
+ "11.0"
416
+ ]
417
+ },
418
+ "execution_count": 12,
419
+ "metadata": {},
420
+ "output_type": "execute_result"
421
+ }
422
+ ],
423
+ "source": [
424
+ "client.version"
425
+ ]
426
+ },
427
+ {
428
+ "cell_type": "markdown",
429
+ "metadata": {},
430
+ "source": [
431
+ "<a class=\"anchor\" id=\"get\"></a>\n",
432
+ "# Get Metadata and Spectra"
433
+ ]
434
+ },
435
+ {
436
+ "cell_type": "markdown",
437
+ "metadata": {},
438
+ "source": [
439
+ "<a class=\"anchor\" id=\"find\"></a>\n",
440
+ "## Get Metadata: `client.find`"
441
+ ]
442
+ },
443
+ {
444
+ "cell_type": "markdown",
445
+ "metadata": {},
446
+ "source": [
447
+ "The first way you can discover your data is by using SPARCL's `client.find()` method, which allows you to find records in the SPARCL database based on certain parameters passed to the function. Only Core fields may be in the `outfields` and `constraints` parameters. The descriptions for all fields, including Core fields, is located [here](https://astrosparcl.datalab.noirlab.edu/sparc/sfc/). The SPARCL Core fields constraint types are:\n",
448
+ "\n",
449
+ "\n",
450
+ "| Field name | Constraint type | Example |\n",
451
+ "|:----------------|:---------------|:-------|\n",
452
+ "| id | List of values (but not<br>intended for data discovery) | ['00001658-460c-4da1-987d-e493d8c9b89b',<br>'000017b6-56a2-4f87-8828-3a3409ba1083']\n",
453
+ "| specid | List of values | [6988698046080241664, 6971782884823945216]\n",
454
+ "| targetid | List of values | [1237679502171374316, 1237678619584692841]\n",
455
+ "| data_release | List of allowed values<br>from [SPARCL Categoricals](https://astrosparcl.datalab.noirlab.edu/sparc/cats/) | ['BOSS-DR16', 'SDSS-DR16']\n",
456
+ "| datasetgroup | List of allowed values<br>from [SPARCL Categoricals](https://astrosparcl.datalab.noirlab.edu/sparc/cats/) | ['SDSS_BOSS']\n",
457
+ "| ra | Range of values (may not<br>\"wrap\" around RA=0) | [44.53, 47.96]\n",
458
+ "| dec | Range of values | [2.03, 7.76]\n",
459
+ "| redshift | Range of values | [0.5, 0.9]\n",
460
+ "| redshift_err | Range of values | [0.000225, 0.000516]\n",
461
+ "| redshift_warning | List of values | [0, 3, 5]\n",
462
+ "| spectype | List of allowed values<br>from [SPARCL Categoricals](https://astrosparcl.datalab.noirlab.edu/sparc/cats/) | ['GALAXY', 'STAR']\n",
463
+ "| instrument | List of allowed values<br>from [SPARCL Categoricals](https://astrosparcl.datalab.noirlab.edu/sparc/cats/) | ['SDSS', 'BOSS']\n",
464
+ "| telescope | List of allowed values<br>from [SPARCL Categoricals](https://astrosparcl.datalab.noirlab.edu/sparc/cats/) | ['sloan25m']\n",
465
+ "| site | List of allowed values<br>from [SPARCL Categoricals](https://astrosparcl.datalab.noirlab.edu/sparc/cats/) | ['apo']\n",
466
+ "| specprimary | List of values (but typically<br>would only include 1 if<br>being used for data<br>discovery constraints) | [1]\n",
467
+ "| wavemin | Range of values | [3607, 3608]\n",
468
+ "| wavemax | Range of values | [10363, 10364]\n",
469
+ "| dateobs_center | Range of values | ['2013-03-14T10:16:17Z',<br>'2014-05-24T12:10:00Z']\n",
470
+ "| exptime | Range of values | [3603.46, 3810.12]\n",
471
+ "| updated | Range of values | ['2022-08-20T21:37:50.636363Z',<br>'2022-09-20T20:00:00.000000Z']\n"
472
+ ]
473
+ },
474
+ {
475
+ "cell_type": "code",
476
+ "execution_count": 13,
477
+ "metadata": {
478
+ "editable": true,
479
+ "scrolled": true,
480
+ "slideshow": {
481
+ "slide_type": ""
482
+ },
483
+ "tags": []
484
+ },
485
+ "outputs": [],
486
+ "source": [
487
+ "if show_help:\n",
488
+ " client.find?"
489
+ ]
490
+ },
491
+ {
492
+ "cell_type": "markdown",
493
+ "metadata": {},
494
+ "source": [
495
+ "#### Define fields and constraints for metadata FIND\n",
496
+ "Define the fields we want returned (`outfields`) and the constraints (`constraints`)"
497
+ ]
498
+ },
499
+ {
500
+ "cell_type": "code",
501
+ "execution_count": 14,
502
+ "metadata": {
503
+ "tags": []
504
+ },
505
+ "outputs": [],
506
+ "source": [
507
+ "out = ['sparcl_id','specid', 'ra', 'dec', 'redshift', 'spectype', 'data_release', 'redshift_err']\n",
508
+ "cons = {'spectype': ['GALAXY'],\n",
509
+ " 'redshift': [0.5, 0.9],\n",
510
+ " 'data_release': ['BOSS-DR16', 'SDSS-DR16']}"
511
+ ]
512
+ },
513
+ {
514
+ "cell_type": "markdown",
515
+ "metadata": {},
516
+ "source": [
517
+ "#### Execute FIND\n",
518
+ "Execute the `client.find()` method with our parameters.\n",
519
+ "The `limit` argument here is being used for demonstration purposes only, and simply returns only the first 20 results here."
520
+ ]
521
+ },
522
+ {
523
+ "cell_type": "code",
524
+ "execution_count": 15,
525
+ "metadata": {
526
+ "scrolled": true,
527
+ "tags": []
528
+ },
529
+ "outputs": [
530
+ {
531
+ "name": "stdout",
532
+ "output_type": "stream",
533
+ "text": [
534
+ "url=http://localhost:8050/sparc/find/?limit=20 sspec={'outfields': ['sparcl_id', 'specid', 'ra', 'dec', 'redshift', 'spectype', 'data_release', 'redshift_err'], 'search': [['spectype', 'GALAXY'], ['redshift', 0.5, 0.9], ['data_release', 'BOSS-DR16', 'SDSS-DR16']]}\n",
535
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"specid\", \"ra\", \"dec\", \"redshift\", \"spectype\", \"data_release\", \"redshift_err\"], \"search\": [[\"spectype\", \"GALAXY\"], [\"redshift\", 0.5, 0.9], [\"data_release\", \"BOSS-DR16\", \"SDSS-DR16\"]]}' 'http://localhost:8050/sparc/find/?limit=20' | python3 -m json.tool\n",
536
+ "Record key counts: {'spectype': 20, 'redshift': 20, 'sparcl_id': 20, 'ra': 20, 'dec': 20, 'specid': 20, '_dr': 20, 'data_release': 20, 'redshift_err': 20}\n"
537
+ ]
538
+ }
539
+ ],
540
+ "source": [
541
+ "found = client.find(outfields=out, constraints=cons, limit=20)"
542
+ ]
543
+ },
544
+ {
545
+ "cell_type": "code",
546
+ "execution_count": null,
547
+ "metadata": {
548
+ "scrolled": true
549
+ },
550
+ "outputs": [],
551
+ "source": []
552
+ },
553
+ {
554
+ "cell_type": "code",
555
+ "execution_count": 16,
556
+ "metadata": {
557
+ "tags": []
558
+ },
559
+ "outputs": [
560
+ {
561
+ "data": {
562
+ "text/html": [
563
+ "<div>\n",
564
+ "<style scoped>\n",
565
+ " .dataframe tbody tr th:only-of-type {\n",
566
+ " vertical-align: middle;\n",
567
+ " }\n",
568
+ "\n",
569
+ " .dataframe tbody tr th {\n",
570
+ " vertical-align: top;\n",
571
+ " }\n",
572
+ "\n",
573
+ " .dataframe thead th {\n",
574
+ " text-align: right;\n",
575
+ " }\n",
576
+ "</style>\n",
577
+ "<table border=\"1\" class=\"dataframe\">\n",
578
+ " <thead>\n",
579
+ " <tr style=\"text-align: right;\">\n",
580
+ " <th></th>\n",
581
+ " <th>redshift</th>\n",
582
+ " <th>ra</th>\n",
583
+ " <th>dec</th>\n",
584
+ " <th>data_release</th>\n",
585
+ " <th>specid</th>\n",
586
+ " <th>redshift_err</th>\n",
587
+ " <th>spectype</th>\n",
588
+ " <th>sparcl_id</th>\n",
589
+ " <th>_dr</th>\n",
590
+ " </tr>\n",
591
+ " </thead>\n",
592
+ " <tbody>\n",
593
+ " <tr>\n",
594
+ " <th>0</th>\n",
595
+ " <td>0.545929</td>\n",
596
+ " <td>246.74298</td>\n",
597
+ " <td>35.985258</td>\n",
598
+ " <td>SDSS-DR16</td>\n",
599
+ " <td>1506516519029336064</td>\n",
600
+ " <td>0.000422</td>\n",
601
+ " <td>GALAXY</td>\n",
602
+ " <td>2c6c82dc-fe87-11ee-838b-08002725f1ef</td>\n",
603
+ " <td>SDSS-DR16</td>\n",
604
+ " </tr>\n",
605
+ " <tr>\n",
606
+ " <th>1</th>\n",
607
+ " <td>0.667431</td>\n",
608
+ " <td>245.40676</td>\n",
609
+ " <td>36.438884</td>\n",
610
+ " <td>SDSS-DR16</td>\n",
611
+ " <td>1506548404866541568</td>\n",
612
+ " <td>0.000026</td>\n",
613
+ " <td>GALAXY</td>\n",
614
+ " <td>3063feb6-fe87-11ee-8aa0-08002725f1ef</td>\n",
615
+ " <td>SDSS-DR16</td>\n",
616
+ " </tr>\n",
617
+ " <tr>\n",
618
+ " <th>2</th>\n",
619
+ " <td>0.502511</td>\n",
620
+ " <td>246.45702</td>\n",
621
+ " <td>36.657405</td>\n",
622
+ " <td>SDSS-DR16</td>\n",
623
+ " <td>1506572869000259584</td>\n",
624
+ " <td>0.000172</td>\n",
625
+ " <td>GALAXY</td>\n",
626
+ " <td>336d71cf-fe87-11ee-9390-08002725f1ef</td>\n",
627
+ " <td>SDSS-DR16</td>\n",
628
+ " </tr>\n",
629
+ " <tr>\n",
630
+ " <th>3</th>\n",
631
+ " <td>0.724874</td>\n",
632
+ " <td>246.89323</td>\n",
633
+ " <td>37.209662</td>\n",
634
+ " <td>SDSS-DR16</td>\n",
635
+ " <td>1506578916314212352</td>\n",
636
+ " <td>11.831918</td>\n",
637
+ " <td>GALAXY</td>\n",
638
+ " <td>342e5eaa-fe87-11ee-9047-08002725f1ef</td>\n",
639
+ " <td>SDSS-DR16</td>\n",
640
+ " </tr>\n",
641
+ " <tr>\n",
642
+ " <th>4</th>\n",
643
+ " <td>0.741196</td>\n",
644
+ " <td>247.40873</td>\n",
645
+ " <td>36.381456</td>\n",
646
+ " <td>SDSS-DR16</td>\n",
647
+ " <td>1506596508500256768</td>\n",
648
+ " <td>0.614932</td>\n",
649
+ " <td>GALAXY</td>\n",
650
+ " <td>36565b1b-fe87-11ee-b857-08002725f1ef</td>\n",
651
+ " <td>SDSS-DR16</td>\n",
652
+ " </tr>\n",
653
+ " <tr>\n",
654
+ " <th>5</th>\n",
655
+ " <td>0.675723</td>\n",
656
+ " <td>134.10755</td>\n",
657
+ " <td>28.038851</td>\n",
658
+ " <td>BOSS-DR16</td>\n",
659
+ " <td>-6444647351317147648</td>\n",
660
+ " <td>0.000241</td>\n",
661
+ " <td>GALAXY</td>\n",
662
+ " <td>5182df54-fe87-11ee-a660-08002725f1ef</td>\n",
663
+ " <td>BOSS-DR16</td>\n",
664
+ " </tr>\n",
665
+ " <tr>\n",
666
+ " <th>6</th>\n",
667
+ " <td>0.782685</td>\n",
668
+ " <td>134.23727</td>\n",
669
+ " <td>28.084685</td>\n",
670
+ " <td>BOSS-DR16</td>\n",
671
+ " <td>-6444646251805519872</td>\n",
672
+ " <td>0.000242</td>\n",
673
+ " <td>GALAXY</td>\n",
674
+ " <td>51ad9b94-fe87-11ee-af3e-08002725f1ef</td>\n",
675
+ " <td>BOSS-DR16</td>\n",
676
+ " </tr>\n",
677
+ " <tr>\n",
678
+ " <th>7</th>\n",
679
+ " <td>0.797439</td>\n",
680
+ " <td>133.98095</td>\n",
681
+ " <td>28.226386</td>\n",
682
+ " <td>BOSS-DR16</td>\n",
683
+ " <td>-6444643503026450432</td>\n",
684
+ " <td>0.000424</td>\n",
685
+ " <td>GALAXY</td>\n",
686
+ " <td>521321c8-fe87-11ee-946d-08002725f1ef</td>\n",
687
+ " <td>BOSS-DR16</td>\n",
688
+ " </tr>\n",
689
+ " <tr>\n",
690
+ " <th>8</th>\n",
691
+ " <td>0.647712</td>\n",
692
+ " <td>134.54531</td>\n",
693
+ " <td>28.429551</td>\n",
694
+ " <td>BOSS-DR16</td>\n",
695
+ " <td>-6444641304003194880</td>\n",
696
+ " <td>0.000238</td>\n",
697
+ " <td>GALAXY</td>\n",
698
+ " <td>52643970-fe87-11ee-abb3-08002725f1ef</td>\n",
699
+ " <td>BOSS-DR16</td>\n",
700
+ " </tr>\n",
701
+ " <tr>\n",
702
+ " <th>9</th>\n",
703
+ " <td>0.886086</td>\n",
704
+ " <td>134.46525</td>\n",
705
+ " <td>28.452505</td>\n",
706
+ " <td>BOSS-DR16</td>\n",
707
+ " <td>-6444640754247380992</td>\n",
708
+ " <td>0.000274</td>\n",
709
+ " <td>GALAXY</td>\n",
710
+ " <td>5278859e-fe87-11ee-8427-08002725f1ef</td>\n",
711
+ " <td>BOSS-DR16</td>\n",
712
+ " </tr>\n",
713
+ " <tr>\n",
714
+ " <th>10</th>\n",
715
+ " <td>0.898559</td>\n",
716
+ " <td>134.43695</td>\n",
717
+ " <td>28.450988</td>\n",
718
+ " <td>BOSS-DR16</td>\n",
719
+ " <td>-6444640204491567104</td>\n",
720
+ " <td>0.000311</td>\n",
721
+ " <td>GALAXY</td>\n",
722
+ " <td>52913c34-fe87-11ee-844b-08002725f1ef</td>\n",
723
+ " <td>BOSS-DR16</td>\n",
724
+ " </tr>\n",
725
+ " <tr>\n",
726
+ " <th>11</th>\n",
727
+ " <td>0.566015</td>\n",
728
+ " <td>133.95386</td>\n",
729
+ " <td>27.305313</td>\n",
730
+ " <td>BOSS-DR16</td>\n",
731
+ " <td>-6444639654735753216</td>\n",
732
+ " <td>0.000315</td>\n",
733
+ " <td>GALAXY</td>\n",
734
+ " <td>52a796f0-fe87-11ee-b337-08002725f1ef</td>\n",
735
+ " <td>BOSS-DR16</td>\n",
736
+ " </tr>\n",
737
+ " <tr>\n",
738
+ " <th>12</th>\n",
739
+ " <td>0.599517</td>\n",
740
+ " <td>134.05133</td>\n",
741
+ " <td>27.381025</td>\n",
742
+ " <td>BOSS-DR16</td>\n",
743
+ " <td>-6444639104979939328</td>\n",
744
+ " <td>0.000412</td>\n",
745
+ " <td>GALAXY</td>\n",
746
+ " <td>52bbb47f-fe87-11ee-b8d7-08002725f1ef</td>\n",
747
+ " <td>BOSS-DR16</td>\n",
748
+ " </tr>\n",
749
+ " <tr>\n",
750
+ " <th>13</th>\n",
751
+ " <td>0.812179</td>\n",
752
+ " <td>133.95189</td>\n",
753
+ " <td>27.333753</td>\n",
754
+ " <td>BOSS-DR16</td>\n",
755
+ " <td>-6444638555224125440</td>\n",
756
+ " <td>0.000338</td>\n",
757
+ " <td>GALAXY</td>\n",
758
+ " <td>52cfb971-fe87-11ee-be51-08002725f1ef</td>\n",
759
+ " <td>BOSS-DR16</td>\n",
760
+ " </tr>\n",
761
+ " <tr>\n",
762
+ " <th>14</th>\n",
763
+ " <td>0.795586</td>\n",
764
+ " <td>134.21014</td>\n",
765
+ " <td>27.571681</td>\n",
766
+ " <td>BOSS-DR16</td>\n",
767
+ " <td>-6444638005468311552</td>\n",
768
+ " <td>0.000337</td>\n",
769
+ " <td>GALAXY</td>\n",
770
+ " <td>52e3cf35-fe87-11ee-b89c-08002725f1ef</td>\n",
771
+ " <td>BOSS-DR16</td>\n",
772
+ " </tr>\n",
773
+ " <tr>\n",
774
+ " <th>15</th>\n",
775
+ " <td>0.554642</td>\n",
776
+ " <td>134.11568</td>\n",
777
+ " <td>27.491442</td>\n",
778
+ " <td>BOSS-DR16</td>\n",
779
+ " <td>-6444636356200869888</td>\n",
780
+ " <td>0.000287</td>\n",
781
+ " <td>GALAXY</td>\n",
782
+ " <td>53203e47-fe87-11ee-b26f-08002725f1ef</td>\n",
783
+ " <td>BOSS-DR16</td>\n",
784
+ " </tr>\n",
785
+ " <tr>\n",
786
+ " <th>16</th>\n",
787
+ " <td>0.688878</td>\n",
788
+ " <td>134.19652</td>\n",
789
+ " <td>27.657880</td>\n",
790
+ " <td>BOSS-DR16</td>\n",
791
+ " <td>-6444635256689242112</td>\n",
792
+ " <td>0.000177</td>\n",
793
+ " <td>GALAXY</td>\n",
794
+ " <td>534af931-fe87-11ee-8467-08002725f1ef</td>\n",
795
+ " <td>BOSS-DR16</td>\n",
796
+ " </tr>\n",
797
+ " <tr>\n",
798
+ " <th>17</th>\n",
799
+ " <td>0.638226</td>\n",
800
+ " <td>133.85629</td>\n",
801
+ " <td>28.080178</td>\n",
802
+ " <td>BOSS-DR16</td>\n",
803
+ " <td>-6444633057665986560</td>\n",
804
+ " <td>0.000194</td>\n",
805
+ " <td>GALAXY</td>\n",
806
+ " <td>539b0add-fe87-11ee-b991-08002725f1ef</td>\n",
807
+ " <td>BOSS-DR16</td>\n",
808
+ " </tr>\n",
809
+ " <tr>\n",
810
+ " <th>18</th>\n",
811
+ " <td>0.614235</td>\n",
812
+ " <td>133.79296</td>\n",
813
+ " <td>27.907149</td>\n",
814
+ " <td>BOSS-DR16</td>\n",
815
+ " <td>-6444632233032265728</td>\n",
816
+ " <td>0.000294</td>\n",
817
+ " <td>GALAXY</td>\n",
818
+ " <td>53b9cd41-fe87-11ee-8132-08002725f1ef</td>\n",
819
+ " <td>BOSS-DR16</td>\n",
820
+ " </tr>\n",
821
+ " <tr>\n",
822
+ " <th>19</th>\n",
823
+ " <td>0.804484</td>\n",
824
+ " <td>133.87033</td>\n",
825
+ " <td>28.192423</td>\n",
826
+ " <td>BOSS-DR16</td>\n",
827
+ " <td>-6444631408398544896</td>\n",
828
+ " <td>0.000317</td>\n",
829
+ " <td>GALAXY</td>\n",
830
+ " <td>53d853da-fe87-11ee-9f77-08002725f1ef</td>\n",
831
+ " <td>BOSS-DR16</td>\n",
832
+ " </tr>\n",
833
+ " </tbody>\n",
834
+ "</table>\n",
835
+ "</div>"
836
+ ],
837
+ "text/plain": [
838
+ " redshift ra dec data_release specid \\\n",
839
+ "0 0.545929 246.74298 35.985258 SDSS-DR16 1506516519029336064 \n",
840
+ "1 0.667431 245.40676 36.438884 SDSS-DR16 1506548404866541568 \n",
841
+ "2 0.502511 246.45702 36.657405 SDSS-DR16 1506572869000259584 \n",
842
+ "3 0.724874 246.89323 37.209662 SDSS-DR16 1506578916314212352 \n",
843
+ "4 0.741196 247.40873 36.381456 SDSS-DR16 1506596508500256768 \n",
844
+ "5 0.675723 134.10755 28.038851 BOSS-DR16 -6444647351317147648 \n",
845
+ "6 0.782685 134.23727 28.084685 BOSS-DR16 -6444646251805519872 \n",
846
+ "7 0.797439 133.98095 28.226386 BOSS-DR16 -6444643503026450432 \n",
847
+ "8 0.647712 134.54531 28.429551 BOSS-DR16 -6444641304003194880 \n",
848
+ "9 0.886086 134.46525 28.452505 BOSS-DR16 -6444640754247380992 \n",
849
+ "10 0.898559 134.43695 28.450988 BOSS-DR16 -6444640204491567104 \n",
850
+ "11 0.566015 133.95386 27.305313 BOSS-DR16 -6444639654735753216 \n",
851
+ "12 0.599517 134.05133 27.381025 BOSS-DR16 -6444639104979939328 \n",
852
+ "13 0.812179 133.95189 27.333753 BOSS-DR16 -6444638555224125440 \n",
853
+ "14 0.795586 134.21014 27.571681 BOSS-DR16 -6444638005468311552 \n",
854
+ "15 0.554642 134.11568 27.491442 BOSS-DR16 -6444636356200869888 \n",
855
+ "16 0.688878 134.19652 27.657880 BOSS-DR16 -6444635256689242112 \n",
856
+ "17 0.638226 133.85629 28.080178 BOSS-DR16 -6444633057665986560 \n",
857
+ "18 0.614235 133.79296 27.907149 BOSS-DR16 -6444632233032265728 \n",
858
+ "19 0.804484 133.87033 28.192423 BOSS-DR16 -6444631408398544896 \n",
859
+ "\n",
860
+ " redshift_err spectype sparcl_id _dr \n",
861
+ "0 0.000422 GALAXY 2c6c82dc-fe87-11ee-838b-08002725f1ef SDSS-DR16 \n",
862
+ "1 0.000026 GALAXY 3063feb6-fe87-11ee-8aa0-08002725f1ef SDSS-DR16 \n",
863
+ "2 0.000172 GALAXY 336d71cf-fe87-11ee-9390-08002725f1ef SDSS-DR16 \n",
864
+ "3 11.831918 GALAXY 342e5eaa-fe87-11ee-9047-08002725f1ef SDSS-DR16 \n",
865
+ "4 0.614932 GALAXY 36565b1b-fe87-11ee-b857-08002725f1ef SDSS-DR16 \n",
866
+ "5 0.000241 GALAXY 5182df54-fe87-11ee-a660-08002725f1ef BOSS-DR16 \n",
867
+ "6 0.000242 GALAXY 51ad9b94-fe87-11ee-af3e-08002725f1ef BOSS-DR16 \n",
868
+ "7 0.000424 GALAXY 521321c8-fe87-11ee-946d-08002725f1ef BOSS-DR16 \n",
869
+ "8 0.000238 GALAXY 52643970-fe87-11ee-abb3-08002725f1ef BOSS-DR16 \n",
870
+ "9 0.000274 GALAXY 5278859e-fe87-11ee-8427-08002725f1ef BOSS-DR16 \n",
871
+ "10 0.000311 GALAXY 52913c34-fe87-11ee-844b-08002725f1ef BOSS-DR16 \n",
872
+ "11 0.000315 GALAXY 52a796f0-fe87-11ee-b337-08002725f1ef BOSS-DR16 \n",
873
+ "12 0.000412 GALAXY 52bbb47f-fe87-11ee-b8d7-08002725f1ef BOSS-DR16 \n",
874
+ "13 0.000338 GALAXY 52cfb971-fe87-11ee-be51-08002725f1ef BOSS-DR16 \n",
875
+ "14 0.000337 GALAXY 52e3cf35-fe87-11ee-b89c-08002725f1ef BOSS-DR16 \n",
876
+ "15 0.000287 GALAXY 53203e47-fe87-11ee-b26f-08002725f1ef BOSS-DR16 \n",
877
+ "16 0.000177 GALAXY 534af931-fe87-11ee-8467-08002725f1ef BOSS-DR16 \n",
878
+ "17 0.000194 GALAXY 539b0add-fe87-11ee-b991-08002725f1ef BOSS-DR16 \n",
879
+ "18 0.000294 GALAXY 53b9cd41-fe87-11ee-8132-08002725f1ef BOSS-DR16 \n",
880
+ "19 0.000317 GALAXY 53d853da-fe87-11ee-9f77-08002725f1ef BOSS-DR16 "
881
+ ]
882
+ },
883
+ "execution_count": 16,
884
+ "metadata": {},
885
+ "output_type": "execute_result"
886
+ }
887
+ ],
888
+ "source": [
889
+ "pd.DataFrame.from_records(found.records)"
890
+ ]
891
+ },
892
+ {
893
+ "cell_type": "markdown",
894
+ "metadata": {},
895
+ "source": [
896
+ "<a class=\"anchor\" id=\"retrieve\"></a>\n",
897
+ "## Get Spectra: `client.retrieve`"
898
+ ]
899
+ },
900
+ {
901
+ "cell_type": "markdown",
902
+ "metadata": {},
903
+ "source": [
904
+ "In order to retrieve spectra records from SPARCL, pass the following to the `client.retrieve()` function:\n",
905
+ "```\n",
906
+ "uuid_list : List of IDs.\n",
907
+ "dataset_list : List of data sets to search for the IDs in (default: None).\n",
908
+ "include : List of field names to include in each record (default: 'DEFAULT').\n",
909
+ "```\n",
910
+ "\n",
911
+ "**NOTE: A reasonable amount of records to request retrieval of is about 10,000. Exceeding this value may cause the retrieval to timeout or fail.**"
912
+ ]
913
+ },
914
+ {
915
+ "cell_type": "code",
916
+ "execution_count": 17,
917
+ "metadata": {
918
+ "scrolled": true,
919
+ "tags": []
920
+ },
921
+ "outputs": [],
922
+ "source": [
923
+ "if show_help:\n",
924
+ " client.retrieve?"
925
+ ]
926
+ },
927
+ {
928
+ "cell_type": "markdown",
929
+ "metadata": {},
930
+ "source": [
931
+ "#### Use IDs from FIND to RETRIEVE records\n",
932
+ "Use the IDs from the output of using `client.find()` to retrieve records from SPARCL. \n",
933
+ "\n",
934
+ "Note that `ids` in `found_I.ids` is a property name of the Found class. It is a list of records from all records, not a field name of a record."
935
+ ]
936
+ },
937
+ {
938
+ "cell_type": "code",
939
+ "execution_count": 18,
940
+ "metadata": {
941
+ "tags": []
942
+ },
943
+ "outputs": [],
944
+ "source": [
945
+ "# Define the fields to include in the retrieve function\n",
946
+ "inc = ['specid', 'data_release', 'redshift', 'flux', 'wavelength', 'model', 'ivar', 'mask', 'spectype']"
947
+ ]
948
+ },
949
+ {
950
+ "cell_type": "code",
951
+ "execution_count": 19,
952
+ "metadata": {
953
+ "tags": []
954
+ },
955
+ "outputs": [
956
+ {
957
+ "name": "stdout",
958
+ "output_type": "stream",
959
+ "text": [
960
+ "Using url=\"http://localhost:8050/sparc/spectras/?include=mask%2Cspectype%2Cmodel%2Credshift%2Cwavelength%2Cspecid%2Civar%2Cdata_release%2Cflux&format=pkl&dataset_list=SDSS-DR16%2CBOSS-DR16\"\n",
961
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '[\"2c6c82dc-fe87-11ee-838b-08002725f1ef\", \"3063feb6-fe87-11ee-8aa0-08002725f1ef\", \"336d71cf-fe87-11ee-9390-08002725f1ef\", \"342e5eaa-fe87-11ee-9047-08002725f1ef\", \"36565b1b-fe87-11ee-b857-08002725f1ef\", \"5182df54-fe87-11ee-a660-08002725f1ef\", \"51ad9b94-fe87-11ee-af3e-08002725f1ef\", \"521321c8-fe87-11ee-946d-08002725f1ef\", \"52643970-fe87-11ee-abb3-08002725f1ef\", \"5278859e-fe87-11ee-8427-08002725f1ef\", \"52913c34-fe87-11ee-844b-08002725f1ef\", \"52a796f0-fe87-11ee-b337-08002725f1ef\", \"52bbb47f-fe87-11ee-b8d7-08002725f1ef\", \"52cfb971-fe87-11ee-be51-08002725f1ef\", \"52e3cf35-fe87-11ee-b89c-08002725f1ef\", \"53203e47-fe87-11ee-b26f-08002725f1ef\", \"534af931-fe87-11ee-8467-08002725f1ef\", \"539b0add-fe87-11ee-b991-08002725f1ef\", \"53b9cd41-fe87-11ee-8132-08002725f1ef\", \"53d853da-fe87-11ee-9f77-08002725f1ef\"]' 'http://localhost:8050/sparc/spectras/?include=mask%2Cspectype%2Cmodel%2Credshift%2Cwavelength%2Cspecid%2Civar%2Cdata_release%2Cflux&format=pkl&dataset_list=SDSS-DR16%2CBOSS-DR16' | python3 -m json.tool\n",
962
+ "Got response to post in 0.264625997049734 seconds\n",
963
+ "Got 20 spectra in 0.26 seconds (76 spectra/sec)\n",
964
+ "{'success': True, 'info': [\"Successfully found 20 records in dr_list=['SDSS-DR16', 'BOSS-DR16']\"], 'warnings': []}\n",
965
+ "CPU times: user 7.69 ms, sys: 10 ms, total: 17.7 ms\n",
966
+ "Wall time: 269 ms\n"
967
+ ]
968
+ },
969
+ {
970
+ "data": {
971
+ "text/plain": [
972
+ "{'status': {'success': True,\n",
973
+ " 'info': [\"Successfully found 20 records in dr_list=['SDSS-DR16', 'BOSS-DR16']\"],\n",
974
+ " 'warnings': []}}"
975
+ ]
976
+ },
977
+ "execution_count": 19,
978
+ "metadata": {},
979
+ "output_type": "execute_result"
980
+ }
981
+ ],
982
+ "source": [
983
+ "%%time\n",
984
+ "results = client.retrieve(uuid_list=found.ids,\n",
985
+ " include=inc,\n",
986
+ " dataset_list=['SDSS-DR16','BOSS-DR16'])\n",
987
+ "results.info"
988
+ ]
989
+ },
990
+ {
991
+ "cell_type": "code",
992
+ "execution_count": 20,
993
+ "metadata": {
994
+ "tags": []
995
+ },
996
+ "outputs": [
997
+ {
998
+ "data": {
999
+ "text/plain": [
1000
+ "{'redshift': 0.5459291338920593,\n",
1001
+ " 'specid': 1506516519029336064,\n",
1002
+ " 'spectype': 'GALAXY',\n",
1003
+ " 'data_release': 'SDSS-DR16',\n",
1004
+ " '_dr': 'SDSS-DR16',\n",
1005
+ " 'ivar': array([0., 0., 0., ..., 0., 0., 0.]),\n",
1006
+ " 'mask': array([16777216, 16777216, 16777216, ..., 16777216, 16777216, 16777216]),\n",
1007
+ " 'flux': array([1.23176956, 1.23148859, 1.23120809, ..., 4.00684404, 4.00690508,\n",
1008
+ " 4.00696611]),\n",
1009
+ " 'wavelength': array([3794.89706208, 3795.77097003, 3796.64507922, ..., 9217.22098659,\n",
1010
+ " 9219.34357452, 9221.46665124]),\n",
1011
+ " 'model': array([0.34971759, 0.35207507, 0.35443148, ..., 2.31373858, 2.30945611,\n",
1012
+ " 2.30356026])}"
1013
+ ]
1014
+ },
1015
+ "execution_count": 20,
1016
+ "metadata": {},
1017
+ "output_type": "execute_result"
1018
+ }
1019
+ ],
1020
+ "source": [
1021
+ "results.records[0]"
1022
+ ]
1023
+ },
1024
+ {
1025
+ "cell_type": "markdown",
1026
+ "metadata": {},
1027
+ "source": [
1028
+ "## Plot spectra"
1029
+ ]
1030
+ },
1031
+ {
1032
+ "cell_type": "code",
1033
+ "execution_count": 21,
1034
+ "metadata": {
1035
+ "tags": []
1036
+ },
1037
+ "outputs": [
1038
+ {
1039
+ "data": {
1040
+ "text/plain": [
1041
+ "<matplotlib.legend.Legend at 0x7fd1f96db7c0>"
1042
+ ]
1043
+ },
1044
+ "execution_count": 21,
1045
+ "metadata": {},
1046
+ "output_type": "execute_result"
1047
+ },
1048
+ {
1049
+ "data": {
1050
+ "application/vnd.jupyter.widget-view+json": {
1051
+ "model_id": "84c674d2919c4a9f804a778cb667076f",
1052
+ "version_major": 2,
1053
+ "version_minor": 0
1054
+ },
1055
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAyAAAAGQCAYAAABWJQQ0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAACFfklEQVR4nO3dd3gUVdsG8Hu2JqQCCRAgDQhI70gvUlUUFURREVB4bXwWVBAEaQKiKGIvqCCCDRQUUHoNvQSQGiDUAKEmJKRsOd8fyW62l2Szu0nu33VxkcycnTk7mZ2dZ845z5GEEAJEREREREReIPN1BYiIiIiIqPxgAEJERERERF7DAISIiIiIiLyGAQgREREREXkNAxAiIiIiIvIaBiBEREREROQ1DECIiIiIiMhrGIAQEREREZHXMAAhIiIiIiKvYQBCRERERERewwCEiIiIiIi8hgEIERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIiIiIjIaxiAEBERERGR1zAAISIiIiIir2EAQkREREREXsMAhIiIiIiIvIYBCBEREREReQ0DECIiIiIi8hoGIERERERE5DUMQIiIiIiIyGsYgBARERERkdcwACEiIiIiIq9hAEJERERERF7DAISIiIiIiLyGAQgREREREXkNAxAiIiIiIvIaBiBEREREROQ1DECIiIiIiMhrGIAQEREREZHXMAAhIiIiIiKvYQBCRERERERewwCEiIiIiIi8hgEIERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIiIiIjIaxiAEBERERGR1zAAISIiIiIir2EAQkREREREXsMAhIiIiIiIvIYBCBEREREReQ0DECIiIiIi8hoGIERERERE5DUKX1eACun1eqSmpiIkJASSJPm6OkRERERkQQiB27dvo3r16pDJ+Cy/KBiA+JHU1FRER0f7uhpERERE5MT58+dRs2ZNX1ejVGIA4kdCQkIA5J/QoaGhPq4NEREREVnKyMhAdHS08b6N3McAxI8Yul2FhoYyACEiIiLyY+wuX3TsuEZERERERF7DAISIiIiIiLyGAQgREREREXkNAxAiIiIiIvIaBiBEREREROQ1DECIiIiIiMhrmIaXiIiIqIBOp4NGo/F1NciL5HI5lEqlr6tRrjAAISIionJPCIHLly8jPT0dQghfV4e8TK1WIyIigvOw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ujrkZWq1GjVq1EBoaKivq1IuMAAhIiKick+SJERFRaFKlSrGsQBUPsjlcna78jIGIEREREQFDONBiKjkcBA6ERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIiIiIjIaxiAEBERERGR1zAAISIiIiIir2EAQkREREREXsMAhIiIiIiIvIYBCBFRGSCEr2tARETkGgYgRERERETkNQxAiIiIiIjIaxiAEBGVAZLk6xoQERG5hgEIEVEZwDEgRERUWjAAISIiIiIir2EAQkREREREXsMAhIioDOAYECIiKi0YgBARlQEcA0JERKUFAxAiIiIiIvIaBiBEREREROQ1DECIiIiIiMhrGIAQEREREZHXMAAhIiIiIiKvYQBCRERERERewwCEiIiIiIi8hgEIERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIjKAAHh6yoQERG5hAEIERERERF5DQMQIqIyQILk6yoQERG5hAEIERERERF5DQMQIqIygGNAiIiotGAAQkREREREXsMAhIioDOAYECIiKi0YgBARERERkdcwACEiKgM4BoSIiEoLBiBEREREROQ1DECIiIiIiMhrGIAQEREREZHXMACx8NNPP+G5555Dq1atoFarIUkS5s2bZ7d8RkYGRo0ahdjYWKjVasTFxeHNN99EZmam9ypNRERERFRKKHxdAX8zfvx4nD17FhEREYiKisLZs2ftls3KykKXLl2QlJSEXr16YdCgQdi/fz9mzZqFTZs2YfPmzQgICPBi7YmIiIiI/BtbQCzMnTsXZ86cwdWrV/H88887LPv+++8jKSkJY8aMwapVq/Dee+9h1apVGDNmDHbv3o3Zs2d7qdZERIWEYEYsIiLyXwxALPTo0QOxsbFOywkhMHfuXAQHB2PChAlm6yZMmIDg4GDMnTu3pKpJRERERFQqMQApouTkZKSmpqJDhw4ICgoyWxcUFIQOHTrg9OnTOH/+vI9qSERERETkfxiAFFFycjIAICEhweZ6w3JDOSIiIiIi4iD0IktPTwcAhIWF2VwfGhpqVs6W3Nxc5ObmGn/PyMjwYA2JiIiIiPwPW0B8aMaMGQgLCzP+i46O9nWViKgM4Bh0IvJ3By/cwpu/H0BaRo6vq0I+wACkiAwtH/ZaOAytGfZaSABg7NixSE9PN/7jeBEiIiIqDx78LBG/772A138/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",
1056
+ "text/html": [
1057
+ "\n",
1058
+ " <div style=\"display: inline-block;\">\n",
1059
+ " <div class=\"jupyter-widgets widget-label\" style=\"text-align: center;\">\n",
1060
+ " Figure\n",
1061
+ " </div>\n",
1062
+ " <img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAGQCAYAAABWJQQ0AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAACFfklEQVR4nO3dd3gUVdsG8Hu2JqQCCRAgDQhI70gvUlUUFURREVB4bXwWVBAEaQKiKGIvqCCCDRQUUHoNvQSQGiDUAKEmJKRsOd8fyW62l2Szu0nu33VxkcycnTk7mZ2dZ845z5GEEAJEREREREReIPN1BYiIiIiIqPxgAEJERERERF7DAISIiIiIiLyGAQgREREREXkNAxAiIiIiIvIaBiBEREREROQ1DECIiIiIiMhrGIAQEREREZHXMAAhIiIiIiKvYQBCRERERERewwCEiIiIiIi8hgEIERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIiIiIjIaxiAEBERERGR1zAAISIiIiIir2EAQkREREREXsMAhIiIiIiIvIYBCBEREREReQ0DECIiIiIi8hoGIERERERE5DUMQIiIiIiIyGsYgBARERERkdcwACEiIiIiIq9hAEJERERERF7DAISIiIiIiLyGAQgREREREXkNAxAiIiIiIvIaBiBEREREROQ1DECIiIiIiMhrGIAQEREREZHXMAAhIiIiIiKvYQBCRERERERewwCEiIiIiIi8hgEIERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIiIiIjIaxiAEBERERGR1zAAISIiIiIir2EAQkREREREXsMAhIiIiIiIvIYBCBEREREReQ0DECIiIiIi8hoGIERERERE5DUKX1eACun1eqSmpiIkJASSJPm6OkRERERkQQiB27dvo3r16pDJ+Cy/KBiA+JHU1FRER0f7uhpERERE5MT58+dRs2ZNX1ejVGIA4kdCQkIA5J/QoaGhPq4NEREREVnKyMhAdHS08b6N3McAxI8Yul2FhoYyACEiIiLyY+wuX3TsuEZERERERF7DAISIiIiIiLyGAQgREREREXkNAxAiIiIiIvIaBiBEREREROQ1DECIiIiIiMhrmIaXiIiIqIBOp4NGo/F1NciL5HI5lEqlr6tRrjAAISIionJPCIHLly8jPT0dQghfV4e8TK1WIyIigvOweQkDECIiIir30tPTcevWLURGRiIoKIiTzJUTQghoNBqkp6fj4sWLAMAgxAsYgBARlRF6vYBMxpsmIncJIZCWlobQ0FBERET4ujrkZYGBgQgJCcGFCxdw7do1BiBewEHoRERlQI5Gh66zNuLVX/b7uipEpY5Op4NOp+ONZzkmSRLCwsKQm5vLMUBewACEiKgMWHPkCs7duIOlSam+rgpRqaPVagEACgU7hpRnhoHoOp3OxzUp+xiAEBEREQEc91HO8e/vPQxAiIiIiIjIaxiAEBGVAUwaSkTFodFoMGnSJCQkJECtVkOSJHz88ceQJAlDhw71dfWojGFnRyIiIqJy7sMPP8TkyZPRuXNnDBw4EEqlEn369MFrr73m66pRGcQAhIioDGDPZSIqjuXLlyM4OBhr1qyBSqUCAJw5c8a3laIyi12wiIiIiMq51NRUVK5c2Rh8EJUkBiBERGUAx4AQUVFMmjQJkiQhJSUFZ8+ehSRJkCQJcXFxdl8TFxdnd33Xrl3Nskldv34dNWvWREhICE6ePGlW1tE6KtvYBYuIiIionOratSsA4OOPPwYAvPrqqwCA8PBwj2y/cuXK+PHHH9GzZ0888cQTSExMNM638eyzz+LixYuYN28e6tSp45H9UenAAISIiIionOratSu6du2KefPmAchvETHw1BiQe+65B6NHj8Z7772H8ePHY+bMmfjiiy+wbNkyDBo0CEOGDPHIfqj0YABCRFQGcBA6kecJIZCt8f9ZsQOVcr+fRG/KlClYt24dZs2ahZo1a2LMmDGIi4vDV1995euqkQ8wACEiKgM4BoTI87I1OjR4Z5Wvq+HUkSm9UUHl37d0SqUSP//8M5o1a4aXX34ZcrkcCxcuRGhoqK+rRj7AQehEREREVOJq1aqFpk2bAgBatmyJ9u3b+7hG5Cv+HS4TERER+UigUo4jU3r7uhpOBSrlXt2fTCZDXl6ezXXp6el2X/fRRx8hMTERlStXxq5du/DFF1/gxRdfLKlqkh9jAEJERERkgyRJft+1yRcqVqyIQ4cOQavVQqEoPD5ZWVlITk62+Zr9+/dj3LhxqFevHjZs2IAOHTrgjTfeQJcuXdCwYUNvVZ38BLtgEREREZHLWrduDY1Gg4ULFxqXCSEwduxYZGVlWZXPysrCoEGDAAA///wzoqKisGjRImg0GgwaNAg5OTleqzv5BwYgREREROSykSNHQqVSYfjw4Xjqqafw2muvoXXr1li5cqVxjIepV155BcePH8f06dPRvHlzAEDbtm0xceJEHDp0CG+++aa33wL5GAMQExcvXsTHH3+MXr16ISYmBiqVCtWqVUP//v2xc+dOm6/JyMjAqFGjEBsbC7Vajbi4OLz55pvIzMz0cu2JiIiISl6jRo3w77//omXLlli8eDEWLFiABg0aYNu2bVYTGC5ZsgTfffcdevbsiVGjRpmtGzduHDp37ozPPvsMy5cv9+I7IF+ThBDM3ljgrbfewsyZM1G7dm107doVkZGRSE5OxtKlSyGEwKJFi/DYY48Zy2dlZaFjx45ISkpCr1690Lx5c+zfvx+rV69G69atsXnzZgQEBLi8/4yMDISFhSE9PZ1p6YjILX8dSMXLP+8HAJx5734f14aodMnJyUFKSgri4+Pd+t6mssXV84D3a8XHkVUm2rRpg40bN6JLly5my7ds2YLu3bvjhRdewEMPPQS1Wg0AeP/995GUlIQxY8bgvffeM5Y3BDKzZ8/G2LFjvfoeiIiIiIj8GbtgmXjkkUesgg8A6NSpE7p164abN2/i0KFDAPIHW82dOxfBwcGYMGGCWfkJEyYgODgYc+fO9Uq9iYiIiIhKCwYgLlIqlQBgTDeXnJyM1NRUdOjQAUFBQWZlg4KC0KFDB5w+fRrnz5/3el2JiIiIiPwVAxAXnDt3DmvXrkVUVBQaN24MAMY81wkJCTZfY1huLx82EREREVF5xDEgTmg0GgwePBi5ubmYOXMm5PL82UYNM32GhYXZfJ1hUJKjGUFzc3ORm5tr/D0jI8NT1SYiIiIi8ktsAXFAr9dj6NCh2Lx5M0aMGIHBgwd7dPszZsxAWFiY8V90dLRHt09ERERE5G8YgNih1+vxzDPPYNGiRXjqqafw1Vdfma03tHzYa+EwtGbYayEBgLFjxyI9Pd34j+NFiIiIiKisYxcsG/R6PYYNG4Yff/wRgwYNwrx58yCTmcdqzsZ4OBsjAgBqtdqY0peIqDg4pRMREZUWbAGxYBp8PPbYY1iwYIFx3IephIQEVK9eHYmJicjKyjJbl5WVhcTERMTHx7NbFRERERGRCQYgJgzdrn788Uc8+uij+Omnn2wGHwAgSRKGDx+OzMxMTJ061Wzd1KlTkZmZiREjRnij2kREkCTJ11UgIiJyCbtgmZgyZQrmz5+P4OBg1K1bF++++65VmYceegjNmjUDAIwePRrLli3DzJkzsX//frRo0QL79u3D6tWr0bp1a7z66qvefQNEVG6xCxYREZUWDEBMnDlzBgCQmZmJadOm2SwTFxdnDECCgoKwadMmTJo0CUuWLMGGDRsQFRWF119/HRMnTkRgYKCXak5EREREVDowADExb948zJs3z63XhIWFYfbs2Zg9e3bJVIqIiIiIqAzhGBAiojKAY0CIqKzZuHEjJEnCpEmTirWduLg4xMXFeaRO5BkMQIiIygCOASEiotKCAQgREREREXkNAxAiIiIiIvIaBiBERERE5ZzpeItt27ahW7duCAkJQWRkJF588UVkZ2cDAFasWIF27dohKCgIVatWxejRo6HVas22pdVq8dFHH6Fp06YIDAxEWFgYunXrhr///tvmvrOzs/HWW28hOjoaAQEBaNSoEb799luH9U1JScHw4cMRExMDtVqNqKgoDB06FGfPnvXMAaESxQCEiIiIiAAAO3fuRPfu3REWFobnnnsOMTEx+PLLLzFixAj8+uuvGDBgAGJjY/Hcc88hPDwcH3zwAaZPn258vRACAwYMwOuvv46cnBy89NJLeOKJJ3DgwAE8+OCDVllD9Xo9HnzwQcycORMVK1bEK6+8grZt2+K1117Dhx9+aLeOzZs3x/z589GyZUu88sor6NSpExYuXIg2bdrg9OnTJXqMqPiYhpeIiIjIFiEAzR1f18I5ZQXAQ5nw/v33XyxduhT9+vUDAGg0GrRq1QqLFi3CqlWrsHnzZrRu3RoAMHnyZNSpUwdz5szB2LFjoVQqsWDBAixbtgxdunTB6tWroVKpAABjx45Fy5YtMXr0aPTr1w+1atUCAPz4449Yu3Yt+vTpg+XLl0MulwMAXnnlFbRq1cqqfhqNBo8//jj0ej127dqF5s2bG9dt3boVXbt2xSuvvGK3tYX8AwMQIiIiIls0d4Dp1X1dC+fGpQKqII9sqlu3bsbgAwCUSiUGDBiAgwcP4oEHHjAGHwAQEhKCvn374vvvv8eFCxcQHx+P+fPnAwDef/99Y/ABADExMXjttdfw9ttvY+HChZgwYQKA/AAEAKZNm2YMPgCgcePGGDx4ML777juz+i1fvhxnzpzBlClTzIIPAOjYsSP69euHpUuXIiMjA6GhoR45JuR5DECIiIiICADQrFkzq2VRUVFO16WmpiI+Ph779+9HhQoV0KZNG6uy3bp1AwAkJSUZlx04cABBQUFo0aKFVflOnTpZBSA7duwAABw/ftzm/CCXL1+GXq/HiRMnbLagkH9gAEJERERki7JCfuuCv1NW8NimbLUaKBQKp+s0Gg0AICMjA9HR0Ta3bQhWMjIyjMvS09Ptlq9atarVshs3bgAAFi5caPc9AEBWVpbD9eRbDECIiIiIbJEkj3VtKi9CQ0ORlpZmc93ly5eNZQzCwsJw9epVm+WvXLlic/sA8Pfff6Nv377FrS75CLNgEREREZFHNG/eHHfu3MGuXbus1m3cuBGAeVeupk2bIisrC/v27bMqv2XLFqtld999NwBg+/btnqkw+QQDECIiIiLyiCFDhgDIz3pl6JYFAOfPn8dHH30EhUKBJ5980rh88ODBAIC3334bOp3OuPzQoUNYsGCB1fb79euHmJgYfPTRR9i8ebPVeo1Gg61bt3rs/VDJYBcsIiIiIvKIwYMH448//sCyZcvQpEkT9O3bF1lZWfj1119x48YNfPjhh8YUvEB+wLJo0SL8+++/aN68Oe69917cuHEDP//8M3r16oXly5ebbV+tVmPx4sW499570aVLF9xzzz1o3LgxJEnC2bNnsWXLFlSuXBnHjh3z9lsnNzAAISIiIiKPkCQJixcvxpw5czB//nx8+umnUKlUaNGiBUaNGoUHH3zQrLxMJsOyZcswefJkLFy4EHPmzEHt2rUxe/ZsJCQkWAUgANC6dWscOHAAH3zwAVauXInExESo1WrUqFEDDz30EAYNGuStt0tFJAkhhK8rQfkyMjIQFhaG9PR05q4mIrcsS7qIV35JAgCcee9+31aGqJTJyclBSkoK4uPjERAQ4OvqkI+4eh7wfq34OAaEiIiIiIi8hgEIERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIiIiIjIaxiAEBERERGR1zAAISIiIiIir2EAQkRERASAU6OVb/z7ew8DECIiIirXFAoFAECr1fq4JuRLGo0GACCXy31ck7KPAQgRERGVa3K5HHK5HBkZGb6uCvmIEALp6elQq9VQKpW+rk6Zp/B1BYiIiIh8SZIkVKlSBZcuXYJarUZQUBAkSfJ1tcgLhBDQaDRIT09HZmYmatSo4esqlQsMQIiIiKjcCwsLQ3Z2Nq5du4arV6/6ujrkZWq1GjVq1EBoaKivq1IuMAAhIiKick+SJERFRaFKlSrGsQBUPsjlcna78jIGIEREREQFDONBiKjkcBA6ERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIiIiIjIaxiAEBERERGR1zAAISIiIiIir2EAQkREREREXsMAhIiIiIiIvIYBCBFRGSCEr2tARETkGgYgRERERETkNQxAiIiIiIjIaxiAEBGVAZLk6xoQERG5hgEIEVEZwDEgRERUWjAAISIiIiIir2EAQkREREREXsMAhIioDOAYECIiKi0YgBARlQEcA0JERKUFAxAiIiIiIvIaBiBEREREROQ1DECIiIiIiMhrGIAQEREREZHXMAAhIiIiIiKvYQBCRERERERewwCEiIiIiIi8hgEIERERERF5DQMQIiIiIiLyGgYgRERERETkNQxAiIjKAAHh6yoQERG5hAEIERERERF5DQMQIqIyQILk6yoQERG5hAEIERERERF5DQMQIqIygGNAiIiotGAAQkREREREXsMAhIioDOAYECIiKi0YgBARERERkdcwACEiKgM4BoSIiEoLBiBEREREROQ1DECIiIiIiMhrGIAQEREREZHXMACx8NNPP+G5555Dq1atoFarIUkS5s2bZ7d8RkYGRo0ahdjYWKjVasTFxeHNN99EZmam9ypNRERERFRKKHxdAX8zfvx4nD17FhEREYiKisLZs2ftls3KykKXLl2QlJSEXr16YdCgQdi/fz9mzZqFTZs2YfPmzQgICPBi7YmIiIiI/BtbQCzMnTsXZ86cwdWrV/H88887LPv+++8jKSkJY8aMwapVq/Dee+9h1apVGDNmDHbv3o3Zs2d7qdZERIWEYEYsIiLyXwxALPTo0QOxsbFOywkhMHfuXAQHB2PChAlm6yZMmIDg4GDMnTu3pKpJRERERFQqMQApouTkZKSmpqJDhw4ICgoyWxcUFIQOHTrg9OnTOH/+vI9qSERERETkfxiAFFFycjIAICEhweZ6w3JDOSIiIiIi4iD0IktPTwcAhIWF2VwfGhpqVs6W3Nxc5ObmGn/PyMjwYA2JiIiIiPwPW0B8aMaMGQgLCzP+i46O9nWViKgM4Bh0IvJ3By/cwpu/H0BaRo6vq0I+wACkiAwtH/ZaOAytGfZaSABg7NixSE9PN/7jeBEiIiIqDx78LBG/772A138/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' width=800.0/>\n",
1063
+ " </div>\n",
1064
+ " "
1065
+ ],
1066
+ "text/plain": [
1067
+ "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …"
1068
+ ]
1069
+ },
1070
+ "metadata": {},
1071
+ "output_type": "display_data"
1072
+ }
1073
+ ],
1074
+ "source": [
1075
+ "recs = results.records\n",
1076
+ "idx = 0\n",
1077
+ "fig=plt.figure(1, figsize=(8,4), dpi= 100, facecolor='w', edgecolor='k')\n",
1078
+ "fline, = plt.plot(recs[idx].flux, label=f'flux')\n",
1079
+ "mline, = plt.plot(recs[idx].model, label=f'model')\n",
1080
+ "plt.legend(handles=[fline,mline])"
1081
+ ]
1082
+ },
1083
+ {
1084
+ "cell_type": "markdown",
1085
+ "metadata": {
1086
+ "toc-hr-collapsed": true
1087
+ },
1088
+ "source": [
1089
+ "## Plot FLUX for all records"
1090
+ ]
1091
+ },
1092
+ {
1093
+ "cell_type": "code",
1094
+ "execution_count": 22,
1095
+ "metadata": {
1096
+ "tags": []
1097
+ },
1098
+ "outputs": [
1099
+ {
1100
+ "name": "stdout",
1101
+ "output_type": "stream",
1102
+ "text": [
1103
+ "Ignoring unsupported feature: align_records\n"
1104
+ ]
1105
+ }
1106
+ ],
1107
+ "source": [
1108
+ "print('Ignoring unsupported feature: align_records')"
1109
+ ]
1110
+ },
1111
+ {
1112
+ "cell_type": "code",
1113
+ "execution_count": 23,
1114
+ "metadata": {
1115
+ "tags": []
1116
+ },
1117
+ "outputs": [],
1118
+ "source": [
1119
+ "#import sparcl.gather_2d\n",
1120
+ "#ar_dict, grid = sparcl.gather_2d.align_records(results.records)\n",
1121
+ "#modeldf = pd.DataFrame(data=ar_dict['flux'],columns=grid)\n",
1122
+ "#modeldf.transpose().plot(xlabel='Wavelength', ylabel='Flux', legend=False)"
1123
+ ]
1124
+ },
1125
+ {
1126
+ "cell_type": "markdown",
1127
+ "metadata": {},
1128
+ "source": [
1129
+ "# Authorization\n",
1130
+ "Your access to data is affected by how you login (or don't). Both `client.find` and `client.retrieve` allow you to request data (possibly implictly) from specific Datasets. Its possible for your combination of LOGIN and FIND (or RETIEVE) to work now, but fail later without you changing anything. For instance, if you don't login and ask for data from ALL Datasets at a time when all Datasets are public, your FIND will succeed. But if NOIRLab adds a new Dataset that is private, your same find will fail. To avoid the failure, you would have to explicitly request only the public Datasets, or to login as a user that is authorized to access the private Dataset.\n",
1131
+ "\n",
1132
+ "So summarize, there are three cases in which your FIND or RETRIEVE will be authorized:\n",
1133
+ "1. All Datasets are Public (does not matter what you login status is)\n",
1134
+ "2. You have explicitly requested only Public Datasets (does not matter what you login status is)\n",
1135
+ "3. You are logged in and are authorized to access all the Private Datasets you have (explicitly or implicitly) requested.\n",
1136
+ "\n",
1137
+ "You might be authorized to access one Dataset, but not another. So, you must be careful in case #3 above to explictly request the correct Private Dataset(s)."
1138
+ ]
1139
+ },
1140
+ {
1141
+ "cell_type": "markdown",
1142
+ "metadata": {},
1143
+ "source": [
1144
+ "## Logging in and logging out"
1145
+ ]
1146
+ },
1147
+ {
1148
+ "cell_type": "code",
1149
+ "execution_count": 24,
1150
+ "metadata": {
1151
+ "tags": []
1152
+ },
1153
+ "outputs": [],
1154
+ "source": [
1155
+ "if show_help:\n",
1156
+ " client.login?\n",
1157
+ " client.logout?"
1158
+ ]
1159
+ },
1160
+ {
1161
+ "cell_type": "code",
1162
+ "execution_count": 25,
1163
+ "metadata": {
1164
+ "tags": []
1165
+ },
1166
+ "outputs": [
1167
+ {
1168
+ "name": "stdout",
1169
+ "output_type": "stream",
1170
+ "text": [
1171
+ "Logged in successfully with email='test_user_1@noirlab.edu'\n"
1172
+ ]
1173
+ }
1174
+ ],
1175
+ "source": [
1176
+ "client.login(auth_user, usrpw)"
1177
+ ]
1178
+ },
1179
+ {
1180
+ "cell_type": "code",
1181
+ "execution_count": 26,
1182
+ "metadata": {
1183
+ "scrolled": true,
1184
+ "tags": []
1185
+ },
1186
+ "outputs": [
1187
+ {
1188
+ "data": {
1189
+ "text/plain": [
1190
+ "{'Loggedin_As': 'test_user_1@noirlab.edu',\n",
1191
+ " 'Authorized_Datasets': {'BOSS-DR16',\n",
1192
+ " 'DESI-EDR',\n",
1193
+ " 'SDSS-DR16',\n",
1194
+ " 'SDSS-DR17-test'}}"
1195
+ ]
1196
+ },
1197
+ "execution_count": 26,
1198
+ "metadata": {},
1199
+ "output_type": "execute_result"
1200
+ }
1201
+ ],
1202
+ "source": [
1203
+ "client.authorized"
1204
+ ]
1205
+ },
1206
+ {
1207
+ "cell_type": "code",
1208
+ "execution_count": 27,
1209
+ "metadata": {
1210
+ "tags": []
1211
+ },
1212
+ "outputs": [
1213
+ {
1214
+ "name": "stdout",
1215
+ "output_type": "stream",
1216
+ "text": [
1217
+ "Logged-out successfully. Previously logged-in with email test_user_1@noirlab.edu.\n"
1218
+ ]
1219
+ }
1220
+ ],
1221
+ "source": [
1222
+ "client.logout() # can also be done with client.login(None)"
1223
+ ]
1224
+ },
1225
+ {
1226
+ "cell_type": "code",
1227
+ "execution_count": 28,
1228
+ "metadata": {
1229
+ "tags": []
1230
+ },
1231
+ "outputs": [
1232
+ {
1233
+ "data": {
1234
+ "text/plain": [
1235
+ "{'Loggedin_As': 'Anonymous',\n",
1236
+ " 'Authorized_Datasets': {'BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'}}"
1237
+ ]
1238
+ },
1239
+ "execution_count": 28,
1240
+ "metadata": {},
1241
+ "output_type": "execute_result"
1242
+ }
1243
+ ],
1244
+ "source": [
1245
+ "client.authorized"
1246
+ ]
1247
+ },
1248
+ {
1249
+ "cell_type": "markdown",
1250
+ "metadata": {},
1251
+ "source": [
1252
+ "## FIND"
1253
+ ]
1254
+ },
1255
+ {
1256
+ "cell_type": "code",
1257
+ "execution_count": 29,
1258
+ "metadata": {},
1259
+ "outputs": [],
1260
+ "source": [
1261
+ "out = ['sparcl_id', 'data_release']\n",
1262
+ "\n",
1263
+ "def pass_find(user, drs):\n",
1264
+ " client.login(user, usrpw)\n",
1265
+ " print(f'{client.authorized=}')\n",
1266
+ " try:\n",
1267
+ " if drs is None:\n",
1268
+ " found = client.find(outfields=out, limit=2)\n",
1269
+ " else:\n",
1270
+ " found = client.find(outfields=out, constraints=dict(data_release=drs), limit=2)\n",
1271
+ " print(f'\\nSUCCESS: {found.count=} records from FIND: {user=}; {drs=}')\n",
1272
+ " except Exception as err:\n",
1273
+ " raise Exception(f'\\nFAILED to get records from FIND: {user=}; {drs=}')\n",
1274
+ "\n",
1275
+ "def fail_find(user, drs):\n",
1276
+ " client.login(user, usrpw)\n",
1277
+ " print(f'{client.authorized=}')\n",
1278
+ "\n",
1279
+ " try:\n",
1280
+ " found = client.find(outfields=out, constraints=dict(data_release=drs), limit=2)\n",
1281
+ " raise Exception(f'\\nFAILED: Auth wrongly got {found.count} records in FIND: {user=}; {drs=}')\n",
1282
+ " except Exception as err:\n",
1283
+ " print(f'\\nSUCCESS: Find did not get records. \\n{err}')"
1284
+ ]
1285
+ },
1286
+ {
1287
+ "cell_type": "markdown",
1288
+ "metadata": {},
1289
+ "source": [
1290
+ "### Pass FIND as Authorized with Default DRs"
1291
+ ]
1292
+ },
1293
+ {
1294
+ "cell_type": "code",
1295
+ "execution_count": 30,
1296
+ "metadata": {
1297
+ "tags": []
1298
+ },
1299
+ "outputs": [
1300
+ {
1301
+ "name": "stdout",
1302
+ "output_type": "stream",
1303
+ "text": [
1304
+ "Logged in successfully with email='test_user_1@noirlab.edu'\n",
1305
+ "client.authorized={'Loggedin_As': 'test_user_1@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16', 'SDSS-DR17-test'}}\n",
1306
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': []}\n",
1307
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": []}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1308
+ "Record key counts: {'data_release': 2, 'sparcl_id': 2, '_dr': 2}\n",
1309
+ "\n",
1310
+ "SUCCESS: found.count=2 records from FIND: user='test_user_1@noirlab.edu'; drs=None\n"
1311
+ ]
1312
+ }
1313
+ ],
1314
+ "source": [
1315
+ "pass_find(auth_user, None)"
1316
+ ]
1317
+ },
1318
+ {
1319
+ "cell_type": "markdown",
1320
+ "metadata": {},
1321
+ "source": [
1322
+ "### Pass FIND as Authorized with Priv&Pub DRs"
1323
+ ]
1324
+ },
1325
+ {
1326
+ "cell_type": "code",
1327
+ "execution_count": 31,
1328
+ "metadata": {
1329
+ "scrolled": true,
1330
+ "tags": []
1331
+ },
1332
+ "outputs": [
1333
+ {
1334
+ "name": "stdout",
1335
+ "output_type": "stream",
1336
+ "text": [
1337
+ "Logged in successfully with email='test_user_1@noirlab.edu'\n",
1338
+ "client.authorized={'Loggedin_As': 'test_user_1@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16', 'SDSS-DR17-test'}}\n",
1339
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': [['data_release', 'BOSS-DR16', 'SDSS-DR17-test']]}\n",
1340
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": [[\"data_release\", \"BOSS-DR16\", \"SDSS-DR17-test\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1341
+ "Record key counts: {'data_release': 2, 'sparcl_id': 2, '_dr': 2}\n",
1342
+ "\n",
1343
+ "SUCCESS: found.count=2 records from FIND: user='test_user_1@noirlab.edu'; drs=['BOSS-DR16', 'SDSS-DR17-test']\n"
1344
+ ]
1345
+ }
1346
+ ],
1347
+ "source": [
1348
+ "pass_find(auth_user, [pub_dr,priv_dr])"
1349
+ ]
1350
+ },
1351
+ {
1352
+ "cell_type": "markdown",
1353
+ "metadata": {},
1354
+ "source": [
1355
+ "### Pass FIND as Unauthorized with Default DRs\n",
1356
+ "DRs default to only what are authorized for authenticated user."
1357
+ ]
1358
+ },
1359
+ {
1360
+ "cell_type": "code",
1361
+ "execution_count": 32,
1362
+ "metadata": {
1363
+ "tags": []
1364
+ },
1365
+ "outputs": [
1366
+ {
1367
+ "name": "stdout",
1368
+ "output_type": "stream",
1369
+ "text": [
1370
+ "Logged in successfully with email='test_user_2@noirlab.edu'\n",
1371
+ "client.authorized={'Loggedin_As': 'test_user_2@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1372
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': []}\n",
1373
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": []}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1374
+ "Record key counts: {'data_release': 2, 'sparcl_id': 2, '_dr': 2}\n",
1375
+ "\n",
1376
+ "SUCCESS: found.count=2 records from FIND: user='test_user_2@noirlab.edu'; drs=None\n"
1377
+ ]
1378
+ }
1379
+ ],
1380
+ "source": [
1381
+ "pass_find(unauth_user, None)"
1382
+ ]
1383
+ },
1384
+ {
1385
+ "cell_type": "markdown",
1386
+ "metadata": {},
1387
+ "source": [
1388
+ "### Fail FIND as Unauthorized with Priv&Pub DRs"
1389
+ ]
1390
+ },
1391
+ {
1392
+ "cell_type": "code",
1393
+ "execution_count": 33,
1394
+ "metadata": {
1395
+ "tags": []
1396
+ },
1397
+ "outputs": [
1398
+ {
1399
+ "name": "stdout",
1400
+ "output_type": "stream",
1401
+ "text": [
1402
+ "Logged in successfully with email='test_user_2@noirlab.edu'\n",
1403
+ "client.authorized={'Loggedin_As': 'test_user_2@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1404
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': [['data_release', 'BOSS-DR16', 'SDSS-DR17-test']]}\n",
1405
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": [[\"data_release\", \"BOSS-DR16\", \"SDSS-DR17-test\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1406
+ "Exception: response content=b'{\"errorMessage\": \"test_user_2@noirlab.edu is declined access to datasets [\\'SDSS-DR17-test\\']; drs_requested=[\\'BOSS-DR16\\', \\'SDSS-DR17-test\\'] my_auth=[\\'BOSS-DR16\\', \\'DESI-EDR\\', \\'SDSS-DR16\\']\", \"errorCode\": \"NODRACCESS\", \"statusCode\": 400, \"saved_tb\": \"NoneType: None\\\\n\"}'\n",
1407
+ "\n",
1408
+ "SUCCESS: Find did not get records. \n",
1409
+ "[UNKNOWN] test_user_2@noirlab.edu is declined access to datasets ['SDSS-DR17-test']; drs_requested=['BOSS-DR16', 'SDSS-DR17-test'] my_auth=['BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'] [NODRACCESS] None\n"
1410
+ ]
1411
+ }
1412
+ ],
1413
+ "source": [
1414
+ "fail_find(unauth_user, [pub_dr,priv_dr])"
1415
+ ]
1416
+ },
1417
+ {
1418
+ "cell_type": "markdown",
1419
+ "metadata": {},
1420
+ "source": [
1421
+ "### Pass FIND as Unknown with Default DRs\n",
1422
+ "DRs default to only what are authorized for authenticated user."
1423
+ ]
1424
+ },
1425
+ {
1426
+ "cell_type": "code",
1427
+ "execution_count": 34,
1428
+ "metadata": {
1429
+ "tags": []
1430
+ },
1431
+ "outputs": [
1432
+ {
1433
+ "name": "stdout",
1434
+ "output_type": "stream",
1435
+ "text": [
1436
+ "Logged in successfully with email='test_user_3@noirlab.edu'\n",
1437
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1438
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': []}\n",
1439
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": []}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1440
+ "Record key counts: {'data_release': 2, 'sparcl_id': 2, '_dr': 2}\n",
1441
+ "\n",
1442
+ "SUCCESS: found.count=2 records from FIND: user='test_user_3@noirlab.edu'; drs=None\n"
1443
+ ]
1444
+ }
1445
+ ],
1446
+ "source": [
1447
+ "pass_find(non_user, None)"
1448
+ ]
1449
+ },
1450
+ {
1451
+ "cell_type": "markdown",
1452
+ "metadata": {},
1453
+ "source": [
1454
+ "### Fail FIND as Unknown with Priv&Pub DRs"
1455
+ ]
1456
+ },
1457
+ {
1458
+ "cell_type": "code",
1459
+ "execution_count": 35,
1460
+ "metadata": {
1461
+ "tags": []
1462
+ },
1463
+ "outputs": [
1464
+ {
1465
+ "name": "stdout",
1466
+ "output_type": "stream",
1467
+ "text": [
1468
+ "Logged in successfully with email='test_user_3@noirlab.edu'\n",
1469
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1470
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': [['data_release', 'BOSS-DR16', 'SDSS-DR17-test']]}\n",
1471
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": [[\"data_release\", \"BOSS-DR16\", \"SDSS-DR17-test\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1472
+ "Exception: response content=b'{\"errorMessage\": \"ANONYMOUS is declined access to datasets [\\'SDSS-DR17-test\\']; drs_requested=[\\'BOSS-DR16\\', \\'SDSS-DR17-test\\'] my_auth=[\\'BOSS-DR16\\', \\'DESI-EDR\\', \\'SDSS-DR16\\']\", \"errorCode\": \"NODRACCESS\", \"statusCode\": 400, \"saved_tb\": \"NoneType: None\\\\n\"}'\n",
1473
+ "\n",
1474
+ "SUCCESS: Find did not get records. \n",
1475
+ "[UNKNOWN] ANONYMOUS is declined access to datasets ['SDSS-DR17-test']; drs_requested=['BOSS-DR16', 'SDSS-DR17-test'] my_auth=['BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'] [NODRACCESS] None\n"
1476
+ ]
1477
+ }
1478
+ ],
1479
+ "source": [
1480
+ "fail_find(non_user, [pub_dr,priv_dr])"
1481
+ ]
1482
+ },
1483
+ {
1484
+ "cell_type": "markdown",
1485
+ "metadata": {},
1486
+ "source": [
1487
+ "### Pass FIND as Anonymous with Default DR list \n",
1488
+ "DRs default to only what are authorized for authenticated user."
1489
+ ]
1490
+ },
1491
+ {
1492
+ "cell_type": "code",
1493
+ "execution_count": 36,
1494
+ "metadata": {
1495
+ "tags": []
1496
+ },
1497
+ "outputs": [
1498
+ {
1499
+ "name": "stdout",
1500
+ "output_type": "stream",
1501
+ "text": [
1502
+ "Logged-out successfully. Previously logged-in with email test_user_3@noirlab.edu.\n",
1503
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1504
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': []}\n",
1505
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": []}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1506
+ "Record key counts: {'data_release': 2, 'sparcl_id': 2, '_dr': 2}\n",
1507
+ "\n",
1508
+ "SUCCESS: found.count=2 records from FIND: user=None; drs=None\n"
1509
+ ]
1510
+ }
1511
+ ],
1512
+ "source": [
1513
+ "pass_find(None, None)"
1514
+ ]
1515
+ },
1516
+ {
1517
+ "cell_type": "markdown",
1518
+ "metadata": {},
1519
+ "source": [
1520
+ "### Pass FIND as Anonymous with Public DR"
1521
+ ]
1522
+ },
1523
+ {
1524
+ "cell_type": "code",
1525
+ "execution_count": 37,
1526
+ "metadata": {
1527
+ "tags": []
1528
+ },
1529
+ "outputs": [
1530
+ {
1531
+ "name": "stdout",
1532
+ "output_type": "stream",
1533
+ "text": [
1534
+ "Logged-out successfully. Previously logged-in with email None.\n",
1535
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1536
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': [['data_release', 'BOSS-DR16']]}\n",
1537
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": [[\"data_release\", \"BOSS-DR16\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1538
+ "Record key counts: {'data_release': 2, 'sparcl_id': 2, '_dr': 2}\n",
1539
+ "\n",
1540
+ "SUCCESS: found.count=2 records from FIND: user=None; drs=['BOSS-DR16']\n"
1541
+ ]
1542
+ }
1543
+ ],
1544
+ "source": [
1545
+ "pass_find(None, [pub_dr])"
1546
+ ]
1547
+ },
1548
+ {
1549
+ "cell_type": "markdown",
1550
+ "metadata": {},
1551
+ "source": [
1552
+ "### Fail FIND as Anonymous with Priv&Pub DRs"
1553
+ ]
1554
+ },
1555
+ {
1556
+ "cell_type": "code",
1557
+ "execution_count": 38,
1558
+ "metadata": {
1559
+ "scrolled": true,
1560
+ "tags": []
1561
+ },
1562
+ "outputs": [
1563
+ {
1564
+ "name": "stdout",
1565
+ "output_type": "stream",
1566
+ "text": [
1567
+ "Logged-out successfully. Previously logged-in with email None.\n",
1568
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1569
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': [['data_release', 'BOSS-DR16', 'SDSS-DR17-test']]}\n",
1570
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": [[\"data_release\", \"BOSS-DR16\", \"SDSS-DR17-test\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1571
+ "Exception: response content=b'{\"errorMessage\": \"ANONYMOUS is declined access to datasets [\\'SDSS-DR17-test\\']; drs_requested=[\\'BOSS-DR16\\', \\'SDSS-DR17-test\\'] my_auth=[\\'BOSS-DR16\\', \\'DESI-EDR\\', \\'SDSS-DR16\\']\", \"errorCode\": \"NODRACCESS\", \"statusCode\": 400, \"saved_tb\": \"NoneType: None\\\\n\"}'\n",
1572
+ "\n",
1573
+ "SUCCESS: Find did not get records. \n",
1574
+ "[UNKNOWN] ANONYMOUS is declined access to datasets ['SDSS-DR17-test']; drs_requested=['BOSS-DR16', 'SDSS-DR17-test'] my_auth=['BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'] [NODRACCESS] None\n"
1575
+ ]
1576
+ }
1577
+ ],
1578
+ "source": [
1579
+ "fail_find(None, [pub_dr, priv_dr])"
1580
+ ]
1581
+ },
1582
+ {
1583
+ "cell_type": "markdown",
1584
+ "metadata": {},
1585
+ "source": [
1586
+ "## RETRIEVE"
1587
+ ]
1588
+ },
1589
+ {
1590
+ "cell_type": "code",
1591
+ "execution_count": 39,
1592
+ "metadata": {
1593
+ "scrolled": true
1594
+ },
1595
+ "outputs": [
1596
+ {
1597
+ "name": "stdout",
1598
+ "output_type": "stream",
1599
+ "text": [
1600
+ "client=(sparclclient:1.2.2b8, api:11.0, http://localhost:8050/sparc, client_hash=f7bd410278bee26a425387c598dd47e80a8fcdcb, verbose=True, connect_timeout=1.1, read_timeout=5400.0)\n"
1601
+ ]
1602
+ }
1603
+ ],
1604
+ "source": [
1605
+ "print(f'{client=}')\n",
1606
+ "inc = ['sparcl_id', 'data_release']\n",
1607
+ "\n",
1608
+ "#pub_ids = client.find(constraints=dict(data_release=[pub_dr]),limit=2).ids\n",
1609
+ "#print(f'{pub_ids=}')\n",
1610
+ "#priv_ids = client.find(constraints=dict(data_release=[priv_dr]),limit=2).ids\n",
1611
+ "#print(f'{priv_ids=}')\n",
1612
+ "\n",
1613
+ "def pass_retrieve(user, drs):\n",
1614
+ " client.login(user, usrpw)\n",
1615
+ " print(f'{client.authorized=}')\n",
1616
+ "\n",
1617
+ " if drs is None:\n",
1618
+ " ids = client.find(outfields=['sparcl_id'], limit=2).ids\n",
1619
+ " else:\n",
1620
+ " ids = client.find(outfields=['sparcl_id'], constraints=dict(data_release=drs), limit=2).ids\n",
1621
+ " try:\n",
1622
+ " if drs is None:\n",
1623
+ " got = client.retrieve(uuid_list=ids, include=inc, limit=2)\n",
1624
+ " else:\n",
1625
+ " got = client.retrieve(uuid_list=ids, include=inc, dataset_list=drs, limit=2)\n",
1626
+ " print(f'\\nSUCCESS: {got.count=} records from RETRIEVE: {user=}; {drs=}')\n",
1627
+ " except Exception as err:\n",
1628
+ " raise Exception(f'Auth wrongly refused records from RETRIEVE: {user=}; {drs=}')\n",
1629
+ "\n",
1630
+ "def fail_retrieve(user, drs):\n",
1631
+ " client.login(user, usrpw)\n",
1632
+ " print(f'{client.authorized=}')\n",
1633
+ "\n",
1634
+ " try:\n",
1635
+ " found = client.find(outfields=out, constraints=dict(data_release=drs), limit=2)\n",
1636
+ " raise Exception(f'Auth wrongly got {found.count} records in RETRIEVE: {user=}; {drs=}')\n",
1637
+ " except Exception as err:\n",
1638
+ " print(f'\\nSUCCESS: RETRIEVE did not get records. \\n{err}')"
1639
+ ]
1640
+ },
1641
+ {
1642
+ "cell_type": "markdown",
1643
+ "metadata": {},
1644
+ "source": [
1645
+ "### Pass RETRIEVE as Auth with Default DRs"
1646
+ ]
1647
+ },
1648
+ {
1649
+ "cell_type": "code",
1650
+ "execution_count": 40,
1651
+ "metadata": {
1652
+ "tags": []
1653
+ },
1654
+ "outputs": [
1655
+ {
1656
+ "name": "stdout",
1657
+ "output_type": "stream",
1658
+ "text": [
1659
+ "Logged in successfully with email='test_user_1@noirlab.edu'\n",
1660
+ "client.authorized={'Loggedin_As': 'test_user_1@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16', 'SDSS-DR17-test'}}\n",
1661
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id'], 'search': []}\n",
1662
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\"], \"search\": []}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1663
+ "Record key counts: {'_dr': 2, 'sparcl_id': 2}\n",
1664
+ "Using url=\"http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl\"\n",
1665
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '[\"000923d5-fe87-11ee-acd2-08002725f1ef\", \"0016db04-fe87-11ee-a58b-08002725f1ef\"]' 'http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl' | python3 -m json.tool\n",
1666
+ "Got response to post in 0.23809996293857694 seconds\n",
1667
+ "Got 2 spectra in 0.24 seconds (8 spectra/sec)\n",
1668
+ "{'success': True, 'info': [\"Successfully found 2 records in dr_list={'BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'}\"], 'warnings': []}\n",
1669
+ "\n",
1670
+ "SUCCESS: found.count=20 records from RETRIEVE: user='test_user_1@noirlab.edu'; drs=None\n"
1671
+ ]
1672
+ }
1673
+ ],
1674
+ "source": [
1675
+ "pass_retrieve(auth_user, None)"
1676
+ ]
1677
+ },
1678
+ {
1679
+ "cell_type": "markdown",
1680
+ "metadata": {},
1681
+ "source": [
1682
+ "### Pass RETRIEVE as Auth with Priv&Pub DRs"
1683
+ ]
1684
+ },
1685
+ {
1686
+ "cell_type": "code",
1687
+ "execution_count": 41,
1688
+ "metadata": {},
1689
+ "outputs": [
1690
+ {
1691
+ "name": "stdout",
1692
+ "output_type": "stream",
1693
+ "text": [
1694
+ "Logged in successfully with email='test_user_1@noirlab.edu'\n",
1695
+ "client.authorized={'Loggedin_As': 'test_user_1@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16', 'SDSS-DR17-test'}}\n",
1696
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id'], 'search': [['data_release', 'SDSS-DR17-test', 'BOSS-DR16']]}\n",
1697
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\"], \"search\": [[\"data_release\", \"SDSS-DR17-test\", \"BOSS-DR16\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1698
+ "Record key counts: {'_dr': 2, 'sparcl_id': 2}\n",
1699
+ "Using url=\"http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl&dataset_list=SDSS-DR17-test%2CBOSS-DR16\"\n",
1700
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '[\"510760cd-fe87-11ee-8470-08002725f1ef\", \"5111ce02-fe87-11ee-bea1-08002725f1ef\"]' 'http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl&dataset_list=SDSS-DR17-test%2CBOSS-DR16' | python3 -m json.tool\n",
1701
+ "Got response to post in 0.27477827202528715 seconds\n",
1702
+ "Got 2 spectra in 0.27 seconds (7 spectra/sec)\n",
1703
+ "{'success': True, 'info': [\"Successfully found 2 records in dr_list=['SDSS-DR17-test', 'BOSS-DR16']\"], 'warnings': []}\n",
1704
+ "\n",
1705
+ "SUCCESS: found.count=20 records from RETRIEVE: user='test_user_1@noirlab.edu'; drs=['SDSS-DR17-test', 'BOSS-DR16']\n"
1706
+ ]
1707
+ }
1708
+ ],
1709
+ "source": [
1710
+ "pass_retrieve(auth_user, [priv_dr, pub_dr])"
1711
+ ]
1712
+ },
1713
+ {
1714
+ "cell_type": "markdown",
1715
+ "metadata": {},
1716
+ "source": [
1717
+ "### Pass RETRIEVE as Unauth with Default DRs\n",
1718
+ "DRs default to only what are authorized for authenticated user."
1719
+ ]
1720
+ },
1721
+ {
1722
+ "cell_type": "code",
1723
+ "execution_count": 42,
1724
+ "metadata": {
1725
+ "tags": []
1726
+ },
1727
+ "outputs": [
1728
+ {
1729
+ "name": "stdout",
1730
+ "output_type": "stream",
1731
+ "text": [
1732
+ "Logged in successfully with email='test_user_2@noirlab.edu'\n",
1733
+ "client.authorized={'Loggedin_As': 'test_user_2@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1734
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id'], 'search': []}\n",
1735
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\"], \"search\": []}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1736
+ "Record key counts: {'_dr': 2, 'sparcl_id': 2}\n",
1737
+ "Using url=\"http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl\"\n",
1738
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '[\"000923d5-fe87-11ee-acd2-08002725f1ef\", \"0016db04-fe87-11ee-a58b-08002725f1ef\"]' 'http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl' | python3 -m json.tool\n",
1739
+ "Got response to post in 0.26971720601432025 seconds\n",
1740
+ "Got 2 spectra in 0.27 seconds (7 spectra/sec)\n",
1741
+ "{'success': True, 'info': [\"Successfully found 2 records in dr_list={'BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'}\"], 'warnings': []}\n",
1742
+ "\n",
1743
+ "SUCCESS: found.count=20 records from RETRIEVE: user='test_user_2@noirlab.edu'; drs=None\n"
1744
+ ]
1745
+ }
1746
+ ],
1747
+ "source": [
1748
+ "try:\n",
1749
+ " pass_retrieve(unauth_user, None)\n",
1750
+ "except Exception as err:\n",
1751
+ " display(Markdown(f'#### BUG: {str(err)}'))"
1752
+ ]
1753
+ },
1754
+ {
1755
+ "cell_type": "markdown",
1756
+ "metadata": {},
1757
+ "source": [
1758
+ "### Fail RETRIEVE as Unauth with Priv&Pub DRs"
1759
+ ]
1760
+ },
1761
+ {
1762
+ "cell_type": "code",
1763
+ "execution_count": 43,
1764
+ "metadata": {
1765
+ "scrolled": true
1766
+ },
1767
+ "outputs": [
1768
+ {
1769
+ "name": "stdout",
1770
+ "output_type": "stream",
1771
+ "text": [
1772
+ "Logged in successfully with email='test_user_2@noirlab.edu'\n",
1773
+ "client.authorized={'Loggedin_As': 'test_user_2@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1774
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': [['data_release', 'SDSS-DR17-test', 'BOSS-DR16']]}\n",
1775
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": [[\"data_release\", \"SDSS-DR17-test\", \"BOSS-DR16\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1776
+ "Exception: response content=b'{\"errorMessage\": \"test_user_2@noirlab.edu is declined access to datasets [\\'SDSS-DR17-test\\']; drs_requested=[\\'BOSS-DR16\\', \\'SDSS-DR17-test\\'] my_auth=[\\'BOSS-DR16\\', \\'DESI-EDR\\', \\'SDSS-DR16\\']\", \"errorCode\": \"NODRACCESS\", \"statusCode\": 400, \"saved_tb\": \"NoneType: None\\\\n\"}'\n",
1777
+ "\n",
1778
+ "SUCCESS: RETRIEVE did not get records. \n",
1779
+ "[UNKNOWN] test_user_2@noirlab.edu is declined access to datasets ['SDSS-DR17-test']; drs_requested=['BOSS-DR16', 'SDSS-DR17-test'] my_auth=['BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'] [NODRACCESS] None\n"
1780
+ ]
1781
+ }
1782
+ ],
1783
+ "source": [
1784
+ "fail_retrieve(unauth_user, [priv_dr, pub_dr])"
1785
+ ]
1786
+ },
1787
+ {
1788
+ "cell_type": "markdown",
1789
+ "metadata": {},
1790
+ "source": [
1791
+ "### Pass RETRIEVE as Unknown with Default DRs\n",
1792
+ "DRs default to only what are authorized for authenticated user."
1793
+ ]
1794
+ },
1795
+ {
1796
+ "cell_type": "code",
1797
+ "execution_count": 44,
1798
+ "metadata": {
1799
+ "tags": []
1800
+ },
1801
+ "outputs": [
1802
+ {
1803
+ "name": "stdout",
1804
+ "output_type": "stream",
1805
+ "text": [
1806
+ "Logged in successfully with email='test_user_3@noirlab.edu'\n",
1807
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1808
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id'], 'search': []}\n",
1809
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\"], \"search\": []}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1810
+ "Record key counts: {'_dr': 2, 'sparcl_id': 2}\n",
1811
+ "Using url=\"http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl\"\n",
1812
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '[\"000923d5-fe87-11ee-acd2-08002725f1ef\", \"0016db04-fe87-11ee-a58b-08002725f1ef\"]' 'http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl' | python3 -m json.tool\n",
1813
+ "Got response to post in 0.3079184840898961 seconds\n",
1814
+ "Got 2 spectra in 0.31 seconds (6 spectra/sec)\n",
1815
+ "{'success': True, 'info': [\"Successfully found 2 records in dr_list={'BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'}\"], 'warnings': []}\n",
1816
+ "\n",
1817
+ "SUCCESS: found.count=20 records from RETRIEVE: user='test_user_3@noirlab.edu'; drs=None\n"
1818
+ ]
1819
+ }
1820
+ ],
1821
+ "source": [
1822
+ "try:\n",
1823
+ " pass_retrieve(non_user, None)\n",
1824
+ "except Exception as err:\n",
1825
+ " display(Markdown(f'#### BUG: {str(err)}'))"
1826
+ ]
1827
+ },
1828
+ {
1829
+ "cell_type": "markdown",
1830
+ "metadata": {},
1831
+ "source": [
1832
+ "### Fail RETRIEVE as Unknown with Priv&Pub DRs"
1833
+ ]
1834
+ },
1835
+ {
1836
+ "cell_type": "code",
1837
+ "execution_count": 45,
1838
+ "metadata": {
1839
+ "scrolled": true
1840
+ },
1841
+ "outputs": [
1842
+ {
1843
+ "name": "stdout",
1844
+ "output_type": "stream",
1845
+ "text": [
1846
+ "Logged in successfully with email='test_user_3@noirlab.edu'\n",
1847
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1848
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': [['data_release', 'SDSS-DR17-test', 'BOSS-DR16']]}\n",
1849
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": [[\"data_release\", \"SDSS-DR17-test\", \"BOSS-DR16\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1850
+ "Exception: response content=b'{\"errorMessage\": \"ANONYMOUS is declined access to datasets [\\'SDSS-DR17-test\\']; drs_requested=[\\'BOSS-DR16\\', \\'SDSS-DR17-test\\'] my_auth=[\\'BOSS-DR16\\', \\'DESI-EDR\\', \\'SDSS-DR16\\']\", \"errorCode\": \"NODRACCESS\", \"statusCode\": 400, \"saved_tb\": \"NoneType: None\\\\n\"}'\n",
1851
+ "\n",
1852
+ "SUCCESS: RETRIEVE did not get records. \n",
1853
+ "[UNKNOWN] ANONYMOUS is declined access to datasets ['SDSS-DR17-test']; drs_requested=['BOSS-DR16', 'SDSS-DR17-test'] my_auth=['BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'] [NODRACCESS] None\n"
1854
+ ]
1855
+ }
1856
+ ],
1857
+ "source": [
1858
+ "fail_retrieve(non_user, [priv_dr, pub_dr])"
1859
+ ]
1860
+ },
1861
+ {
1862
+ "cell_type": "markdown",
1863
+ "metadata": {},
1864
+ "source": [
1865
+ "### Pass RETRIEVE as Anon with Default DRs\n",
1866
+ "DRs default to only what are authorized for authenticated user."
1867
+ ]
1868
+ },
1869
+ {
1870
+ "cell_type": "code",
1871
+ "execution_count": 46,
1872
+ "metadata": {
1873
+ "tags": []
1874
+ },
1875
+ "outputs": [
1876
+ {
1877
+ "name": "stdout",
1878
+ "output_type": "stream",
1879
+ "text": [
1880
+ "Logged-out successfully. Previously logged-in with email test_user_3@noirlab.edu.\n",
1881
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1882
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id'], 'search': []}\n",
1883
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\"], \"search\": []}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1884
+ "Record key counts: {'_dr': 2, 'sparcl_id': 2}\n",
1885
+ "Using url=\"http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl\"\n",
1886
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '[\"000923d5-fe87-11ee-acd2-08002725f1ef\", \"0016db04-fe87-11ee-a58b-08002725f1ef\"]' 'http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl' | python3 -m json.tool\n",
1887
+ "Got response to post in 0.03403094399254769 seconds\n",
1888
+ "Got 2 spectra in 0.03 seconds (59 spectra/sec)\n",
1889
+ "{'success': True, 'info': [\"Successfully found 2 records in dr_list={'BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'}\"], 'warnings': []}\n",
1890
+ "\n",
1891
+ "SUCCESS: found.count=20 records from RETRIEVE: user=None; drs=None\n"
1892
+ ]
1893
+ }
1894
+ ],
1895
+ "source": [
1896
+ "try:\n",
1897
+ " pass_retrieve(None, None)\n",
1898
+ "except Exception as err:\n",
1899
+ " display(Markdown(f'#### BUG: {str(err)}'))"
1900
+ ]
1901
+ },
1902
+ {
1903
+ "cell_type": "markdown",
1904
+ "metadata": {},
1905
+ "source": [
1906
+ "### Fail RETRIEVE as Anon with Priv&Pub DR "
1907
+ ]
1908
+ },
1909
+ {
1910
+ "cell_type": "code",
1911
+ "execution_count": 47,
1912
+ "metadata": {
1913
+ "tags": []
1914
+ },
1915
+ "outputs": [
1916
+ {
1917
+ "name": "stdout",
1918
+ "output_type": "stream",
1919
+ "text": [
1920
+ "Logged-out successfully. Previously logged-in with email None.\n",
1921
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1922
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id', 'data_release'], 'search': [['data_release', 'SDSS-DR17-test', 'BOSS-DR16']]}\n",
1923
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\", \"data_release\"], \"search\": [[\"data_release\", \"SDSS-DR17-test\", \"BOSS-DR16\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1924
+ "Exception: response content=b'{\"errorMessage\": \"ANONYMOUS is declined access to datasets [\\'SDSS-DR17-test\\']; drs_requested=[\\'BOSS-DR16\\', \\'SDSS-DR17-test\\'] my_auth=[\\'BOSS-DR16\\', \\'DESI-EDR\\', \\'SDSS-DR16\\']\", \"errorCode\": \"NODRACCESS\", \"statusCode\": 400, \"saved_tb\": \"NoneType: None\\\\n\"}'\n",
1925
+ "\n",
1926
+ "SUCCESS: RETRIEVE did not get records. \n",
1927
+ "[UNKNOWN] ANONYMOUS is declined access to datasets ['SDSS-DR17-test']; drs_requested=['BOSS-DR16', 'SDSS-DR17-test'] my_auth=['BOSS-DR16', 'DESI-EDR', 'SDSS-DR16'] [NODRACCESS] None\n"
1928
+ ]
1929
+ }
1930
+ ],
1931
+ "source": [
1932
+ "fail_retrieve(None, [priv_dr, pub_dr])"
1933
+ ]
1934
+ },
1935
+ {
1936
+ "cell_type": "markdown",
1937
+ "metadata": {},
1938
+ "source": [
1939
+ "### Pass RETRIEVE as Anon with Public DR "
1940
+ ]
1941
+ },
1942
+ {
1943
+ "cell_type": "code",
1944
+ "execution_count": 48,
1945
+ "metadata": {
1946
+ "tags": []
1947
+ },
1948
+ "outputs": [
1949
+ {
1950
+ "name": "stdout",
1951
+ "output_type": "stream",
1952
+ "text": [
1953
+ "Logged-out successfully. Previously logged-in with email None.\n",
1954
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n",
1955
+ "url=http://localhost:8050/sparc/find/?limit=2 sspec={'outfields': ['sparcl_id'], 'search': [['data_release', 'BOSS-DR16']]}\n",
1956
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '{\"outfields\": [\"sparcl_id\"], \"search\": [[\"data_release\", \"BOSS-DR16\"]]}' 'http://localhost:8050/sparc/find/?limit=2' | python3 -m json.tool\n",
1957
+ "Record key counts: {'_dr': 2, 'sparcl_id': 2}\n",
1958
+ "Using url=\"http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl&dataset_list=BOSS-DR16\"\n",
1959
+ "curl -X 'POST' -H 'Content-Type: application/json' -d '[\"510760cd-fe87-11ee-8470-08002725f1ef\", \"5111ce02-fe87-11ee-bea1-08002725f1ef\"]' 'http://localhost:8050/sparc/spectras/?include=data_release%2Csparcl_id&format=pkl&dataset_list=BOSS-DR16' | python3 -m json.tool\n",
1960
+ "Got response to post in 0.0383652689633891 seconds\n",
1961
+ "Got 2 spectra in 0.04 seconds (52 spectra/sec)\n",
1962
+ "{'success': True, 'info': [\"Successfully found 2 records in dr_list=['BOSS-DR16']\"], 'warnings': []}\n",
1963
+ "\n",
1964
+ "SUCCESS: found.count=20 records from RETRIEVE: user=None; drs=['BOSS-DR16']\n"
1965
+ ]
1966
+ }
1967
+ ],
1968
+ "source": [
1969
+ "pass_retrieve(None, [pub_dr])"
1970
+ ]
1971
+ },
1972
+ {
1973
+ "cell_type": "markdown",
1974
+ "metadata": {},
1975
+ "source": [
1976
+ "# All Done"
1977
+ ]
1978
+ },
1979
+ {
1980
+ "cell_type": "code",
1981
+ "execution_count": 49,
1982
+ "metadata": {
1983
+ "tags": []
1984
+ },
1985
+ "outputs": [
1986
+ {
1987
+ "name": "stdout",
1988
+ "output_type": "stream",
1989
+ "text": [
1990
+ "Run finished: 2024-05-02 10:22:39.403970\n"
1991
+ ]
1992
+ }
1993
+ ],
1994
+ "source": [
1995
+ "print(f'Run finished: {str(datetime.now())}')"
1996
+ ]
1997
+ },
1998
+ {
1999
+ "cell_type": "code",
2000
+ "execution_count": 50,
2001
+ "metadata": {
2002
+ "tags": []
2003
+ },
2004
+ "outputs": [
2005
+ {
2006
+ "name": "stdout",
2007
+ "output_type": "stream",
2008
+ "text": [
2009
+ "Logged in successfully with email='test_user_1@noirlab.edu'\n",
2010
+ "\n",
2011
+ "client.authorized={'Loggedin_As': 'test_user_1@noirlab.edu', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16', 'SDSS-DR17-test'}}\n",
2012
+ "\n",
2013
+ "\n",
2014
+ "Logged-out successfully. Previously logged-in with email test_user_1@noirlab.edu.\n",
2015
+ "\n",
2016
+ "client.authorized={'Loggedin_As': 'Anonymous', 'Authorized_Datasets': {'SDSS-DR16', 'DESI-EDR', 'BOSS-DR16'}}\n"
2017
+ ]
2018
+ }
2019
+ ],
2020
+ "source": [
2021
+ "# DLS-496\n",
2022
+ "client.login(auth_user, usrpw)\n",
2023
+ "print(f'\\n{client.authorized=}\\n\\n')\n",
2024
+ "client.logout() # can also be done with client.login(None)\n",
2025
+ "print(f'\\n{client.authorized=}')"
2026
+ ]
2027
+ }
2028
+ ],
2029
+ "metadata": {
2030
+ "kernelspec": {
2031
+ "display_name": "Python 3 (ipykernel)",
2032
+ "language": "python",
2033
+ "name": "python3"
2034
+ },
2035
+ "language_info": {
2036
+ "codemirror_mode": {
2037
+ "name": "ipython",
2038
+ "version": 3
2039
+ },
2040
+ "file_extension": ".py",
2041
+ "mimetype": "text/x-python",
2042
+ "name": "python",
2043
+ "nbconvert_exporter": "python",
2044
+ "pygments_lexer": "ipython3",
2045
+ "version": "3.10.12"
2046
+ },
2047
+ "toc": {
2048
+ "base_numbering": 1
2049
+ },
2050
+ "toc-showmarkdowntxt": false
2051
+ },
2052
+ "nbformat": 4,
2053
+ "nbformat_minor": 4
2054
+ }