adss 1.29__py3-none-any.whl → 1.31__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.
adss/client.py CHANGED
@@ -450,7 +450,7 @@ class ADSSClient:
450
450
 
451
451
  # === Image methods ===
452
452
 
453
- def get_image_collections(self, skip: int = 0, limit: int = 100, **kwargs) -> List[Dict[str, Any]]:
453
+ def get_collections(self, skip: int = 0, limit: int = 100, **kwargs) -> List[Dict[str, Any]]:
454
454
  """
455
455
  Get a list of accessible image collections.
456
456
 
@@ -464,7 +464,7 @@ class ADSSClient:
464
464
  """
465
465
  return self.images.get_collections(skip, limit, **kwargs)
466
466
 
467
- def get_image_collection(self, collection_id: int, **kwargs) -> Dict[str, Any]:
467
+ def get_collection(self, collection_id: int, **kwargs) -> Dict[str, Any]:
468
468
  """
469
469
  Get a specific image collection by ID.
470
470
 
@@ -477,7 +477,7 @@ class ADSSClient:
477
477
  """
478
478
  return self.images.get_collection(collection_id, **kwargs)
479
479
 
480
- def list_image_files(self, collection_id: int, skip: int = 0, limit: int = 100,
480
+ def list_files(self, collection_id: int, skip: int = 0, limit: int = 100,
481
481
  filter_name: Optional[str] = None, filter_str: Optional[str] = None,
482
482
  object_name: Optional[str] = None, **kwargs) -> List[Dict[str, Any]]:
483
483
  """
adss/endpoints/images.py CHANGED
@@ -58,68 +58,6 @@ class ImagesEndpoint:
58
58
  except Exception as e:
59
59
  raise ResourceNotFoundError(f"Failed to get image collection {collection_id}: {e}")
60
60
 
61
- def create_collection(self, name: str, base_path: str, description: Optional[str] = None, **kwargs) -> Dict[str, Any]:
62
- url = f"{self.base_url}/adss/v1/images/collections/"
63
- headers = self.auth_manager._get_auth_headers()
64
- payload = {"name": name, "base_path": base_path}
65
- if description:
66
- payload["description"] = description
67
-
68
- try:
69
- resp = self.auth_manager.request(
70
- method="POST",
71
- url=url,
72
- headers=headers,
73
- json=payload,
74
- auth_required=True,
75
- **kwargs
76
- )
77
- handle_response_errors(resp)
78
- return resp.json()
79
- except Exception as e:
80
- raise ResourceNotFoundError(f"Failed to create image collection: {e}")
81
-
82
- def update_collection(self, collection_id: int, name: Optional[str] = None,
83
- description: Optional[str] = None, **kwargs) -> Dict[str, Any]:
84
- url = f"{self.base_url}/adss/v1/images/collections/{collection_id}"
85
- headers = self.auth_manager._get_auth_headers()
86
- payload: Dict[str, Any] = {}
87
- if name:
88
- payload["name"] = name
89
- if description is not None:
90
- payload["description"] = description
91
-
92
- try:
93
- resp = self.auth_manager.request(
94
- method="PUT",
95
- url=url,
96
- headers=headers,
97
- json=payload,
98
- auth_required=True,
99
- **kwargs
100
- )
101
- handle_response_errors(resp)
102
- return resp.json()
103
- except Exception as e:
104
- raise ResourceNotFoundError(f"Failed to update collection {collection_id}: {e}")
105
-
106
- def delete_collection(self, collection_id: int, **kwargs) -> bool:
107
- url = f"{self.base_url}/adss/v1/images/collections/{collection_id}"
108
- headers = self.auth_manager._get_auth_headers()
109
-
110
- try:
111
- resp = self.auth_manager.request(
112
- method="DELETE",
113
- url=url,
114
- headers=headers,
115
- auth_required=True,
116
- **kwargs
117
- )
118
- handle_response_errors(resp)
119
- return True
120
- except Exception as e:
121
- raise ResourceNotFoundError(f"Failed to delete collection {collection_id}: {e}")
122
-
123
61
  def list_files(self,
124
62
  collection_id: int,
125
63
  skip: int = 0,
@@ -203,7 +141,7 @@ class ImagesEndpoint:
203
141
  url = f"{self.base_url}/adss/v1/images/files/{file_id}/download?token={self.auth_manager.token}"
204
142
 
205
143
  try:
206
- resp = self.auth_manager.request(
144
+ resp = self.auth_manager.download(
207
145
  method="GET",
208
146
  url=url,
209
147
  stream=True,
@@ -226,42 +164,6 @@ class ImagesEndpoint:
226
164
  except Exception as e:
227
165
  raise ResourceNotFoundError(f"Failed to download image file {file_id}: {e}")
228
166
 
229
- def scan_directory(self, collection_id: int, rescan_existing: bool = False, **kwargs) -> Dict[str, Any]:
230
- url = f"{self.base_url}/adss/v1/images/collections/{collection_id}/scan"
231
- headers = self.auth_manager._get_auth_headers()
232
- payload = {"rescan_existing": rescan_existing}
233
-
234
- try:
235
- resp = self.auth_manager.request(
236
- method="POST",
237
- url=url,
238
- headers=headers,
239
- json=payload,
240
- auth_required=True,
241
- **kwargs
242
- )
243
- handle_response_errors(resp)
244
- return resp.json()
245
- except Exception as e:
246
- raise ResourceNotFoundError(f"Failed to scan directory: {e}")
247
-
248
- def get_scan_status(self, job_id: str, **kwargs) -> Dict[str, Any]:
249
- url = f"{self.base_url}/adss/v1/images/scan-jobs/{job_id}"
250
- headers = self.auth_manager._get_auth_headers()
251
-
252
- try:
253
- resp = self.auth_manager.request(
254
- method="GET",
255
- url=url,
256
- headers=headers,
257
- auth_required=False,
258
- **kwargs
259
- )
260
- handle_response_errors(resp)
261
- return resp.json()
262
- except Exception as e:
263
- raise ResourceNotFoundError(f"Failed to get scan job status: {e}")
264
-
265
167
 
266
168
  class LuptonImagesEndpoint:
267
169
  """
@@ -301,7 +203,7 @@ class LuptonImagesEndpoint:
301
203
  payload["size"] = size
302
204
 
303
205
  try:
304
- resp = self.auth_manager.request(
206
+ resp = self.auth_manager.download(
305
207
  method="POST",
306
208
  url=url,
307
209
  headers=headers,
@@ -374,7 +276,7 @@ class LuptonImagesEndpoint:
374
276
  payload["size"] = size
375
277
 
376
278
  try:
377
- resp = self.auth_manager.request(
279
+ resp = self.auth_manager.download(
378
280
  method="POST",
379
281
  url=url,
380
282
  headers=headers,
@@ -421,7 +323,7 @@ class LuptonImagesEndpoint:
421
323
  payload["pattern"] = pattern
422
324
 
423
325
  try:
424
- resp = self.auth_manager.request(
326
+ resp = self.auth_manager.download(
425
327
  method="POST",
426
328
  url=url,
427
329
  headers=headers,
@@ -476,7 +378,7 @@ class LuptonImagesEndpoint:
476
378
  payload["pattern"] = pattern
477
379
 
478
380
  try:
479
- resp = self.auth_manager.request(
381
+ resp = self.auth_manager.download(
480
382
  method="POST",
481
383
  url=url,
482
384
  headers=headers,
@@ -531,7 +433,7 @@ class StampImagesEndpoint:
531
433
  payload["zmax"] = zmax
532
434
 
533
435
  try:
534
- resp = self.auth_manager.request(
436
+ resp = self.auth_manager.download(
535
437
  method="POST",
536
438
  url=url,
537
439
  headers=headers,
@@ -596,7 +498,7 @@ class StampImagesEndpoint:
596
498
  payload["zmax"] = zmax
597
499
 
598
500
  try:
599
- resp = self.auth_manager.request(
501
+ resp = self.auth_manager.download(
600
502
  method="POST",
601
503
  url=url,
602
504
  headers=headers,
@@ -646,7 +548,7 @@ class StampImagesEndpoint:
646
548
  payload["pattern"] = pattern
647
549
 
648
550
  try:
649
- resp = self.auth_manager.request(
551
+ resp = self.auth_manager.download(
650
552
  method="POST",
651
553
  url=url,
652
554
  headers=headers,
@@ -698,7 +600,7 @@ class StampImagesEndpoint:
698
600
  payload["pattern"] = pattern
699
601
 
700
602
  try:
701
- resp = self.auth_manager.request(
603
+ resp = self.auth_manager.download(
702
604
  method="POST",
703
605
  url=url,
704
606
  headers=headers,
@@ -763,7 +665,7 @@ class TrilogyImagesEndpoint:
763
665
  payload["size"] = size
764
666
 
765
667
  try:
766
- resp = self.auth_manager.request(
668
+ resp = self.auth_manager.download(
767
669
  method="POST",
768
670
  url=url,
769
671
  headers=headers,
@@ -812,7 +714,7 @@ class TrilogyImagesEndpoint:
812
714
  payload["pattern"] = pattern
813
715
 
814
716
  try:
815
- resp = self.auth_manager.request(
717
+ resp = self.auth_manager.download(
816
718
  method="POST",
817
719
  url=url,
818
720
  headers=headers,
@@ -868,7 +770,7 @@ class TrilogyImagesEndpoint:
868
770
  payload["pattern"] = pattern
869
771
 
870
772
  try:
871
- resp = self.auth_manager.request(
773
+ resp = self.auth_manager.download(
872
774
  method="POST",
873
775
  url=url,
874
776
  headers=headers,
adss/models/query.py CHANGED
@@ -90,6 +90,19 @@ class Query:
90
90
  def is_failed(self) -> bool:
91
91
  """Check if the query failed."""
92
92
  return self.status == 'failed'
93
+
94
+ def report(self) -> None:
95
+ """Print a summary of the query."""
96
+ print(f"Query ID: {self.id}")
97
+ print(f"Status: {self.status}")
98
+ if self.completed_at:
99
+ print(f"Completed At: {self.completed_at}")
100
+ if self.execution_time_ms is not None:
101
+ print(f"Execution Time (ms): {self.execution_time_ms}")
102
+ if self.row_count is not None:
103
+ print(f"Row Count: {self.row_count}")
104
+ if self.error:
105
+ print(f"Error: {self.error}")
93
106
 
94
107
 
95
108
  @dataclass
@@ -0,0 +1,180 @@
1
+ Metadata-Version: 2.4
2
+ Name: adss
3
+ Version: 1.31
4
+ Summary: Astronomical Data Smart System
5
+ Author-email: Gustavo Schwarz <gustavo.b.schwarz@gmail.com>
6
+ Project-URL: Homepage, https://github.com/schwarzam/adss
7
+ Classifier: Programming Language :: Python :: 3
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: pyarrow
12
+ Requires-Dist: requests
13
+ Requires-Dist: astropy
14
+ Dynamic: license-file
15
+
16
+ # ADSS
17
+ Astronomical Data Smart System
18
+
19
+ ADSS is a database/server project that provides access to ADSS compatible astronomical services.
20
+
21
+ This repository provides a set of tools for querying astronomical ADSS services using ADQL. You can perform cone searches, cross-match queries between tables, and even cross-match against user-supplied data. The library supports both synchronous and asynchronous query execution. Download of images, cutouts, colored images and spectra is also supported.
22
+
23
+ Github repository: [https://github.com/schwarzam/adss](https://github.com/schwarzam/adss)
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install adss
29
+ ```
30
+
31
+ or
32
+
33
+ ```bash
34
+ git clone https://github.com/schwarzam/adss.git
35
+ cd adss
36
+ pip install .
37
+ ```
38
+
39
+
40
+ ### About ADSS compatible services
41
+
42
+ ADSS is a project that is still under development. Currently, some of the ADSS services are available at [https://ai-scope.cbpf.br/](https://ai-scope.cbpf.br/) and [https://splus.cloud/](https://splus.cloud/).
43
+
44
+ ### New Features
45
+
46
+ ADSS supports different queries, including cone searches, cross-matches between tables, and cross-matches against user-supplied data. The library supports both synchronous and asynchronous query execution.
47
+
48
+ Also some improvements in the ADQL parsing were made, allowing queries with wildcards in the SELECT statement, such as:
49
+
50
+ ```sql
51
+ SELECT psf_* FROM my_table WHERE CONTAINS(POINT('ICRS', ra, dec), CIRCLE('ICRS', 150.0, 2.0, 0.1))=1
52
+ ```
53
+
54
+ This will select all columns that start with "psf_".
55
+
56
+
57
+ ### Starting a client
58
+
59
+ To start using ADSS, you need to initialize a client with the base URL of the ADSS service and your credentials. Here's an example:
60
+
61
+ ```python
62
+ import adss
63
+
64
+ cl = adss.ADSSClient(
65
+ base_url="https://ai-scope.cbpf.br/",
66
+ username="your_username",
67
+ password="your_password"
68
+ )
69
+ ```
70
+
71
+ The client will handle authentication and session management for you.
72
+
73
+ ### Performing Queries
74
+
75
+ You can perform various types of queries using the client. ADSS inherited a lot of the concept of the Table Access Protocol (TAP). Specially the sync and async modes of queries.
76
+
77
+ - **Synchronous Queries** (Short Lived Queries): These queries are executed immediately, and the results are returned in the body of the first request if found! With a timeout of ~10 seconds usually. Good for small tables or queries that return a small number of rows <1000. Example:
78
+
79
+ ```python
80
+ cl.query(
81
+ """
82
+ select *
83
+ from my_table
84
+ where CONTAINS(POINT('ICRS', ra, dec), CIRCLE('ICRS', 150.0, 2.0, 0.1))=1
85
+ """
86
+ )
87
+ ```
88
+
89
+ - **Asynchronous Queries**: These queries are executed in the background, and you can check the status of the query and retrieve the results once they are ready. Good for large tables or queries that return a large number of rows or long queries.
90
+
91
+ We have two ways of doing async queries. This first send the query to the server and wait until it's done. Example:
92
+
93
+ ```python
94
+ tab = cl.query_and_wait(
95
+ query_text="""
96
+ select top 100 *
97
+ from splus.splus_idr6 where field = 'HYDRA-0091'
98
+ """,
99
+ mode="adql", # or sql
100
+ file=None, # dataframe
101
+ table_name=None,
102
+ )
103
+ # Print the dataframe
104
+ print(tab.data)
105
+ ```
106
+
107
+ The second way is a more controlled way, where you create the query, check the status and fetch the when you want results:
108
+
109
+ ```python
110
+
111
+ # Create a asynchronous query
112
+ query = cl.async_query(
113
+ query_text="""
114
+ select top 100 id, ra, dec, mag_psf*
115
+ from splus.splus_idr6 where field = 'HYDRA-0091'
116
+ """,
117
+ mode="adql", # or sql
118
+ file=None, # dataframe
119
+ table_name=None,
120
+ )
121
+
122
+ # Check the status of the query and fetch results if complete
123
+ query = cl.queries.get_status(query.id)
124
+ if query.is_complete:
125
+ print("Query is complete. Fetching results...")
126
+ results = cl.queries.get_results(query.id)
127
+ else:
128
+ print("Query is not complete yet.")
129
+
130
+ ```
131
+
132
+ ### Uploading user tables
133
+
134
+ In the last example we left the `file` and `table_name` parameters as `None`. This means that we are not uploading any user table to the server. If you want to upload a user table, you can do it by passing a pandas DataFrame to the `file` parameter and a name for the table to the `table_name` parameter. **The uploaded table should be referenced as upload.`table_name` in the query.**.
135
+
136
+ ```python
137
+ import pandas as pd
138
+ # Create a sample dataframe
139
+ data = {
140
+ "id": [1, 2, 3],
141
+ "ra": [150.1, 150.2, 150.3],
142
+ "dec": [2.1, 2.2, 2.3]
143
+ }
144
+ df = pd.DataFrame(data)
145
+
146
+ # Create a asynchronous query with user table
147
+ query = cl.query_and_wait(
148
+ query_text="""
149
+ select a.*, b.mag_psf_r
150
+ from upload.my_table as a
151
+ join splus.splus_idr6 as b on a.id = b.id
152
+ """,
153
+ mode="adql", # or sql
154
+ file=df, # dataframe
155
+ table_name="my_table",
156
+ )
157
+
158
+ ### Images - File Collections
159
+
160
+ ADSS also supports downloading images, cutouts, colored images. These are handled as Collections. You can list the available file collections in the database metadata:
161
+
162
+ ```python
163
+ cl.get_image_collections()
164
+ ```
165
+
166
+ ```
167
+ [
168
+ {
169
+ 'name': 'splus dr4',
170
+ 'path': '/dados/splus',
171
+ 'description': 'splus dr4 collection',
172
+ 'id': 1,
173
+ 'created_at': '2025-04-22T15:27:36.698058',
174
+ 'updated_at': '2025-07-31T23:27:51.497554',
175
+ 'last_scanned': '2025-05-08T20:28:54.420350',
176
+ 'patterns': {'': 'swp.', 'weight': 'weight'}
177
+ }
178
+ ]
179
+ ```
180
+
@@ -1,21 +1,21 @@
1
1
  adss/__init__.py,sha256=3FpHFL3Pk5BvETwd70P2QqYvDq799Cu2AGxGxudGAAE,1020
2
2
  adss/auth.py,sha256=4eZ5VjqyzF-gXNywjGdjjphd5im3wOFLf5tihKNfbdw,5320
3
- adss/client.py,sha256=dhhO1rXLXhBUbmZacCuZdJAYoP6xFWK9OB2i3Di453g,29914
3
+ adss/client.py,sha256=TIGXsYos9Tt8zSiSwYDdHoPDjiurHoQvH1RVUPeuCK8,29896
4
4
  adss/exceptions.py,sha256=YeN-xRHvlSmwyS8ni2jOEhhgZK9J1jsG11pOedy3Gfg,1482
5
5
  adss/utils.py,sha256=KeQUtTCcye3W07oHpBnwS7g3gG-RqwWMlaE7UgDWwsU,3557
6
6
  adss/endpoints/__init__.py,sha256=Pr29901fT8ClCS2GasTjTiBNyn7DfVfxILpYDFsMvPA,488
7
7
  adss/endpoints/admin.py,sha256=S6ZrkeA_Lh_LCpF1NHyfMKqjbIiylYXUSV65H_WKg1U,16391
8
- adss/endpoints/images.py,sha256=r6YvRo6feAXKd_quK_UQPKe3OSRsDaPr3UHDZ0Cab0I,35588
8
+ adss/endpoints/images.py,sha256=jNKC-zjbVZ89PaRazeh7-30uvPz7-L1mX5w6JXeXl_E,31909
9
9
  adss/endpoints/metadata.py,sha256=RPrRP6Uz6-uPMIcntMgfss9vAd5iN7JXjZbF8SW0EYg,8238
10
10
  adss/endpoints/queries.py,sha256=du4C_K8870ffyZkaLnMD08jMAWeVBygdk_bjgnEEMWM,17633
11
11
  adss/endpoints/users.py,sha256=6Abkl3c3_YKdMYR_JWI-uL9HTHxcjlIOnE29GyN5_QE,10811
12
12
  adss/models/__init__.py,sha256=ADWVaGy4dkpEMH3iS_6EnRSBlEgoM5Vy9zORQr-UG6w,404
13
13
  adss/models/metadata.py,sha256=6fdH_0BenVRmeXkkKbsG2B68O-N2FXTTRgxsEhAHRoU,4058
14
- adss/models/query.py,sha256=Mh7f7pE-YNw58By68CfV-aJ45bPpsurEQeAEhs0CYoM,4308
14
+ adss/models/query.py,sha256=V1H9UAv9wORAr85aajeY7H1zaxyfNtKuEoBtBU66DbM,4820
15
15
  adss/models/user.py,sha256=5qVT5qOktokmVLkGszPGCTZWv0wC-7aBMvJ8EeBOqdw,3493
16
- adss-1.29.dist-info/licenses/LICENSE,sha256=yPw116pnd1J4TuMPnvm6I_irZUyC30EoBZ4BtWFAL7I,1557
16
+ adss-1.31.dist-info/licenses/LICENSE,sha256=yPw116pnd1J4TuMPnvm6I_irZUyC30EoBZ4BtWFAL7I,1557
17
17
  dev/fetch_idr6.py,sha256=b6FrHPr-ZLaDup_wLOaQWP2fK254Sr3YNHbTxuUt088,12788
18
- adss-1.29.dist-info/METADATA,sha256=Fn17y4MlYc3_1mE4MqoDVAhDFYgS7mms5CslsppfOR8,1043
19
- adss-1.29.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
- adss-1.29.dist-info/top_level.txt,sha256=NT2zObOOiTWXc0yowpEjT6BiiI1e7WXlXd0ZoK7T5hk,9
21
- adss-1.29.dist-info/RECORD,,
18
+ adss-1.31.dist-info/METADATA,sha256=h0AEToEPxgL_4FKFjq1Tcf9d_LVhVfWwD1fhF4_DwAA,5656
19
+ adss-1.31.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ adss-1.31.dist-info/top_level.txt,sha256=NT2zObOOiTWXc0yowpEjT6BiiI1e7WXlXd0ZoK7T5hk,9
21
+ adss-1.31.dist-info/RECORD,,
@@ -1,36 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: adss
3
- Version: 1.29
4
- Summary: Astronomical Data Smart System
5
- Author-email: Gustavo Schwarz <gustavo.b.schwarz@gmail.com>
6
- Project-URL: Homepage, https://github.com/schwarzam/adss
7
- Classifier: Programming Language :: Python :: 3
8
- Requires-Python: >=3.8
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: pyarrow
12
- Requires-Dist: requests
13
- Requires-Dist: astropy
14
- Dynamic: license-file
15
-
16
- # ADSS
17
- Astronomical Data Smart System
18
-
19
- ADSS is a database/server project hosted at CBPF (Brazilian Center for Research in Physics) that provides access to astronomical data from different surveys.
20
-
21
- This repository provides a set of tools for querying astronomical ADSS services using ADQL. You can perform cone searches, cross-match queries between tables, and even cross-match against user-supplied data. The library supports both synchronous and asynchronous query execution.
22
-
23
- ## Instalation
24
-
25
- ```bash
26
- pip install adss
27
- ```
28
-
29
- or
30
-
31
- ```bash
32
- git clone https://github.com/schwarzam/adss.git
33
- cd adss
34
- pip install .
35
- ```
36
-
File without changes