timewise 1.0.0a9__py3-none-any.whl → 1.0.0a10__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.
@@ -9,7 +9,7 @@
9
9
 
10
10
  import sys
11
11
  from hashlib import blake2b
12
- from typing import Literal, List
12
+ from typing import Literal, List, Dict, Any
13
13
 
14
14
  import pandas as pd
15
15
 
@@ -88,7 +88,7 @@ class TimewiseAlertSupplier(BaseAlertSupplier, AmpelABC):
88
88
  for i, row in table.iterrows():
89
89
  # convert table row to dict, convert data types from numpy to native python
90
90
  # Respect masked fields and convert to None
91
- pp = {k: None if pd.isna(v) else v for k, v in row.to_dict().items()}
91
+ pp = {str(k): None if pd.isna(v) else v for k, v in row.to_dict().items()}
92
92
  pp_hash = blake2b(encode(pp), digest_size=7).digest()
93
93
  if self.counter:
94
94
  pp["candid"] = self.counter
@@ -37,6 +37,7 @@ else:
37
37
  class T1HDBSCAN(AbsT1CombineUnit):
38
38
  input_mongo_db_name: str
39
39
  original_id_key: str
40
+ mongo: str = "mongodb://localhost:27017/"
40
41
  whitelist_region_arcsec: float = 1
41
42
  cluster_distance_arcsec: float = 0.5
42
43
 
@@ -57,7 +58,7 @@ class T1HDBSCAN(AbsT1CombineUnit):
57
58
 
58
59
  def __init__(self, **kwargs):
59
60
  super().__init__(**kwargs)
60
- self._col = MongoClient()[self.input_mongo_db_name]["input"]
61
+ self._col = MongoClient(self.mongo)[self.input_mongo_db_name]["input"]
61
62
  self._plotter = AuxUnitRegister.new_unit(
62
63
  model=self.plotter, sub_type=AuxDiagnosticPlotter
63
64
  )
@@ -17,7 +17,7 @@ from timewise.process import keys
17
17
 
18
18
  class TimewiseFilter(AbsAlertFilter):
19
19
  det_per_visit: int = 8
20
- n_visits = 10
20
+ n_visits: int = 10
21
21
 
22
22
  def process(self, alert: AmpelAlertProtocol) -> None | bool | int:
23
23
  columns = [
timewise/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "1.0.0a9"
1
+ __version__ = "1.0.0a10"
timewise/chunking.py CHANGED
@@ -11,9 +11,7 @@ logger = logging.getLogger(__name__)
11
11
 
12
12
 
13
13
  class Chunk:
14
- def __init__(
15
- self, chunk_id: int, input_csv, row_indices: npt.NDArray[np.int_]
16
- ):
14
+ def __init__(self, chunk_id: int, input_csv, row_indices: npt.NDArray[np.int_]):
17
15
  self.chunk_id = chunk_id
18
16
  self.row_numbers = row_indices
19
17
  self.input_csv = input_csv
@@ -71,4 +69,4 @@ class Chunker:
71
69
  start = chunk_id * self.chunk_size
72
70
  stop = min(start + self.chunk_size, self._n_rows)
73
71
  logger.debug(f"chunk {chunk_id}: from {start} to {stop}")
74
- return Chunk(chunk_id, self.input_csv, np.arange(start=start, stop=stop))
72
+ return Chunk(chunk_id, self.input_csv, np.arange(start, stop))
timewise/io/stable_tap.py CHANGED
@@ -95,10 +95,32 @@ class StableAsyncTAPJob(vo.dal.AsyncTAPJob):
95
95
  @backoff.on_exception(
96
96
  backoff.expo,
97
97
  vo.dal.DALServiceError,
98
- max_tries=50,
98
+ max_tries=5,
99
99
  )
100
- def _update(self, *args, **kwargs):
101
- return super(StableAsyncTAPJob, self)._update(*args, **kwargs)
100
+ def _update(self, wait_for_statechange=False, timeout=60.0):
101
+ n_tries = 0
102
+ max_tries = 10
103
+ while n_tries < max_tries:
104
+ try:
105
+ res = super(StableAsyncTAPJob, self)._update(
106
+ wait_for_statechange=wait_for_statechange,
107
+ timeout=timeout * (1 + n_tries),
108
+ )
109
+ except vo.dal.DALServiceError as e:
110
+ if "Read timed out" in str(e):
111
+ logger.debug(
112
+ f"{self.url} timed out after {timeout * (1 + n_tries):.0f}s"
113
+ )
114
+ n_tries += 1
115
+ continue
116
+ else:
117
+ raise e
118
+
119
+ return res
120
+
121
+ raise vo.dal.DALServiceError(
122
+ f"No success after {max_tries} tries for {self.url}!"
123
+ )
102
124
 
103
125
 
104
126
  class StableTAPService(vo.dal.TAPService):
@@ -136,6 +158,8 @@ class StableTAPService(vo.dal.TAPService):
136
158
  max_tries=5,
137
159
  )
138
160
  def run_sync(
139
- self, query, *, language="ADQL", maxrec=None, uploads=None,
140
- **keywords):
141
- return super().run_sync(query, language=language, maxrec=maxrec, uploads=uploads, **keywords)
161
+ self, query, *, language="ADQL", maxrec=None, uploads=None, **keywords
162
+ ):
163
+ return super().run_sync(
164
+ query, language=language, maxrec=maxrec, uploads=uploads, **keywords
165
+ )
@@ -10,6 +10,8 @@ from pymongo import MongoClient, ASCENDING
10
10
  from pymongo.collection import Collection
11
11
  from pymongo.database import Database
12
12
 
13
+ from ..util.path import expand
14
+
13
15
  if find_spec("ampel.core"):
14
16
  AMPEL_EXISTS = True
15
17
  from ampel.cli.JobCommand import JobCommand
@@ -40,6 +42,10 @@ class AmpelInterface:
40
42
  self.template_path = Path(template_path)
41
43
  self.uri = uri
42
44
 
45
+ @property
46
+ def expanded_input_csv(self) -> Path:
47
+ return expand(self.input_csv)
48
+
43
49
  def import_input(self):
44
50
  # if collection already exists, assume import was already done
45
51
  if "input" in self.client[self.input_mongo_db_name].list_collection_names():
@@ -48,12 +54,12 @@ class AmpelInterface:
48
54
  )
49
55
  return
50
56
 
51
- logger.debug(f"importing {self.input_csv} into {self.input_mongo_db_name}")
57
+ logger.debug(f"importing {self.expanded_input_csv} into {self.input_mongo_db_name}")
52
58
  col = self.client[self.input_mongo_db_name]["input"]
53
59
 
54
60
  # create an index from stock id
55
61
  col.create_index([(self.orig_id_key, ASCENDING)], unique=True)
56
- col.insert_many(pd.read_csv(self.input_csv).to_dict(orient="records"))
62
+ col.insert_many(pd.read_csv(self.expanded_input_csv).to_dict(orient="records"))
57
63
 
58
64
  def make_ampel_job_file(self, cfg_path: Path) -> Path:
59
65
  logger.debug(f"loading ampel job template from {self.template_path}")
@@ -146,7 +146,7 @@ def calculate_epochs(
146
146
  bias_correction_function = CORRECTION_FUNCTIONS[correction_name]
147
147
 
148
148
  one_points_mask = None
149
- visits_at_least_two_point = []
149
+ visits_at_least_two_point: npt.NDArray[np.generic] = np.array([])
150
150
 
151
151
  while n_remaining_outlier > 0:
152
152
  # make a mask of values to use
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: timewise
3
- Version: 1.0.0a9
3
+ Version: 1.0.0a10
4
4
  Summary: Download WISE infrared data for many objects and process them with AMPEL
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -15,22 +15,22 @@ Classifier: Programming Language :: Python :: 3.13
15
15
  Provides-Extra: ampel
16
16
  Provides-Extra: dev
17
17
  Provides-Extra: docs
18
- Requires-Dist: ampel-alerts (==0.10.3a6) ; extra == "ampel"
19
- Requires-Dist: ampel-core (==0.10.6a17) ; extra == "ampel"
18
+ Requires-Dist: ampel-alerts (==0.10.4a0) ; extra == "ampel"
19
+ Requires-Dist: ampel-core (==0.10.6a21) ; extra == "ampel"
20
20
  Requires-Dist: ampel-interface (==0.10.5a8) ; extra == "ampel"
21
21
  Requires-Dist: ampel-photometry (==0.10.2a1) ; extra == "ampel"
22
22
  Requires-Dist: ampel-plot (>=0.9.1,<0.10.0) ; extra == "ampel"
23
23
  Requires-Dist: astropy (>=5.1,<8.0.0)
24
24
  Requires-Dist: autodoc_pydantic[erdantic] (>=2.2.0,<3.0.0) ; extra == "docs"
25
25
  Requires-Dist: backoff (>=2.1.2,<3.0.0)
26
- Requires-Dist: coveralls (>=3.3.1,<4.0.0) ; extra == "dev"
26
+ Requires-Dist: coveralls (>=4.0.0,<5.0.0) ; extra == "dev"
27
27
  Requires-Dist: jupyter[jupyter] (>=1.0.0,<2.0.0)
28
28
  Requires-Dist: jupyterlab[jupyter] (>=4.0.6,<5.0.0)
29
29
  Requires-Dist: matplotlib (>=3.5.3,<4.0.0)
30
30
  Requires-Dist: mongomock (>=4.3.0,<5.0.0) ; extra == "dev"
31
31
  Requires-Dist: mypy (>=1.18.2,<2.0.0) ; extra == "dev"
32
32
  Requires-Dist: myst-parser (>=1,<3) ; extra == "docs"
33
- Requires-Dist: numpy (>=1.23.2,<2.0.0)
33
+ Requires-Dist: numpy (>=1.23.2,<3.0.0)
34
34
  Requires-Dist: pandas (>=1.4.3,<3.0.0)
35
35
  Requires-Dist: pandas-stubs (>=2.3.2.250926,<3.0.0.0) ; extra == "dev"
36
36
  Requires-Dist: pydantic (>=2.0.0,<3.0.0)
@@ -38,12 +38,12 @@ Requires-Dist: pytest (>=7.2.2,<8.0.0) ; extra == "dev"
38
38
  Requires-Dist: pyvo (>=1.7.0,<2.0.0)
39
39
  Requires-Dist: requests (>=2.28.1,<3.0.0)
40
40
  Requires-Dist: ruff (>=0.13.0,<0.14.0) ; extra == "dev"
41
- Requires-Dist: scikit-image (>=0.19.3,<0.22.0)
41
+ Requires-Dist: scikit-image (>=0.26.0,<0.27.0)
42
42
  Requires-Dist: scikit-learn (>=1.3.0,<2.0.0)
43
43
  Requires-Dist: scipy-stubs (>=1.16.2.0,<2.0.0.0) ; extra == "dev"
44
44
  Requires-Dist: sphinx-rtd-theme (>=1.3.0,<2.0.0) ; extra == "docs"
45
45
  Requires-Dist: tqdm (>=4.64.0,<5.0.0)
46
- Requires-Dist: typer (>=0.19.2,<0.20.0)
46
+ Requires-Dist: typer (>=0.19.2,<0.30.0)
47
47
  Requires-Dist: types-pyyaml (>=6.0.12.20250915,<7.0.0.0) ; extra == "dev"
48
48
  Requires-Dist: types-requests (>=2.32.4.20250913,<3.0.0.0) ; extra == "dev"
49
49
  Requires-Dist: urllib3 (>=2.5.0,<3.0.0)
@@ -61,29 +61,31 @@ Description-Content-Type: text/markdown
61
61
  ![](timewise.png)
62
62
  # Infrared light curves from WISE data
63
63
 
64
- This package downloads WISE data for positions on the sky and stacks single-exposure photometry per visit
64
+ This package downloads WISE data for positions on the sky and stacks single-exposure photometry per visit. It is designed to do so for efficiently for large samples of millions of objects.
65
65
 
66
66
  ## Prerequisites
67
67
  Python version 3.11, 3.12 or 3.13.
68
68
 
69
69
  If you want to not only download individual exposure photometry but also stack detections per visit (see below),
70
- you must have access to a running [MongoDB](https://www.mongodb.com/)*.
70
+ you must have access to a running [MongoDB](https://www.mongodb.com/)* **.
71
71
 
72
72
  <sub>* On MacOS have alook at the custom `brew` tap
73
73
  [here](https://github.com/mongodb/homebrew-brew)
74
74
  to get the MongoDB community edition. </sub>
75
75
 
76
+ <sub>** On some systems this is not straight forward to set up. `timewise` requires it nevertheless as an integral part of the AMPEL system which is used to efficiently schedule and store the stacking of lightcurves. If you do not foresee a big overhead in calculating lightcurves for a sample of O(1000) objects, a more lightweight package might be more applicable. </sub>
77
+
76
78
  ## Installation
77
79
 
78
80
  ### If you use timewise only for downloading
79
81
  The package can be installed via `pip` (but make sure to install the v1 pre-release):
80
82
  ```bash
81
- pip install --pre timewise==1.0.0a9
83
+ pip install --pre timewise==1.0.0a10
82
84
  ```
83
85
  ### If you use timewise also for stacking individual exposures
84
86
  You must install with the `ampel` extra:
85
87
  ```bash
86
- pip install --pre 'timewise[ampel]==1.0.0a9'
88
+ pip install --pre 'timewise[ampel]==1.0.0a10'
87
89
  ```
88
90
  To tell AMPEL which modules, aka units, to use, build the corresponding configuration file:
89
91
  ```bash
@@ -1,25 +1,25 @@
1
- ampel/timewise/alert/TimewiseAlertSupplier.py,sha256=zGpEaObAWWHxZ10lgDCG-uCxmGUx_tJwjfzsQqBmZYY,4200
1
+ ampel/timewise/alert/TimewiseAlertSupplier.py,sha256=M6F0oWhPvqDpeW1S4jbfKcSXutg0wnatSFieR_Ulk5w,4216
2
2
  ampel/timewise/alert/load/TimewiseFileLoader.py,sha256=bmuKys-D7mN3FdVRoIAoOUzH_z5fTw7ph3K-rFJvdIA,4792
3
3
  ampel/timewise/ingest/TiCompilerOptions.py,sha256=j2eUxSkJEKxAjJCd9plxRRCg6Mv8dNHw72UvKyAxUsA,809
4
4
  ampel/timewise/ingest/TiDataPointShaper.py,sha256=KbAg-J0DkMaJA9K67xMY5Pe0SIP0LNKsBNAMnTYV9zA,3180
5
5
  ampel/timewise/ingest/TiMongoMuxer.py,sha256=Y0rt31FEpOd5DxI1IACI6lgNq8ruwCecU4e2nZsQuEA,11381
6
6
  ampel/timewise/ingest/tags.py,sha256=ggn0Y6QUnjIwMzOlgKmPX1JPhmnvc21nUrORFhaR0uI,564
7
- ampel/timewise/t1/T1HDBSCAN.py,sha256=zVhcqQVAjlHgDBd9CJA6rGH3RCrCV84rsIIOWVxODKI,9528
8
- ampel/timewise/t1/TimewiseFilter.py,sha256=uDjNGsqPOISoFjSH8tX87I3UTW9qGX8rEmkyze8u2ug,1566
7
+ ampel/timewise/t1/T1HDBSCAN.py,sha256=5joN-JNtoI_9dk3Q0zl0EGL6jKNCjbz_6tBnxH8Ix0s,9584
8
+ ampel/timewise/t1/TimewiseFilter.py,sha256=rkqI7c6x6vpRPpdVwEGvZLdvcJf8X02vsR2DjOcqki8,1571
9
9
  ampel/timewise/t2/T2StackVisits.py,sha256=JBxFZLT-a-8jjenRw45ZVA_FvtcyOBmvMVcpYHyw_Yk,2574
10
10
  ampel/timewise/util/AuxDiagnosticPlotter.py,sha256=evvuH5vuEOFkfbkoSQw7ztiEqHos19PP91VQ_SCg_AU,1692
11
11
  ampel/timewise/util/pdutil.py,sha256=CJqeYqL2I6A5WnF5S342bwM4omJY-1XwT1XWY2uk3bc,1524
12
- timewise/__init__.py,sha256=UBV5ucjbNEZwWwlTUO9yll_qfeL4UdJ7f9_tRHCgLds,24
12
+ timewise/__init__.py,sha256=8zyDLNzfVXEOy1p7e1MfCjp4ljUWsoJM9LaLeealOa0,25
13
13
  timewise/backend/__init__.py,sha256=w79nWfCw8n9g98CkHWJELmb4j9xblWC4DGZOV3_XhH4,134
14
14
  timewise/backend/base.py,sha256=iZyq_avKCoLuDp6vRNITI6zStQnsBfSaF47tG7DF0Wg,1155
15
15
  timewise/backend/filesystem.py,sha256=wR1kcPWumiwgc72jBSzjbAG4PKPywre3pA4UYJwP134,2685
16
- timewise/chunking.py,sha256=eRd3xof-5uHaxo8Pmwo4kr_cdZSfFpgTiPu-xuL-SGA,2404
16
+ timewise/chunking.py,sha256=C_wbfvraJ_ESIKWcGgH7Usd3cIvC9jUcE6FX8rp14Qs,2379
17
17
  timewise/cli.py,sha256=A1-glt0_JJvS8TOnNjR6jX5SaFUTGhH9p1HC_gyYpHE,4383
18
18
  timewise/config.py,sha256=ZTSokRZMZDqBqVFV9DxvO-47yE9E9xWF48Rcjb0QG10,1044
19
19
  timewise/io/__init__.py,sha256=S7vb0glKJnw6ztOlrD-0Wma2bQZ2RwpmXDLFJLKBMVo,35
20
20
  timewise/io/config.py,sha256=UEmZr-C3_TQKWSsdyFldb6pjn_s7QK9mkZar3Xzp-dM,2611
21
21
  timewise/io/download.py,sha256=FG28Tk4QDW7MZx7pi6xFuoQVcB70aTZMUzbjdFG2RJo,10842
22
- timewise/io/stable_tap.py,sha256=VWlKGj6WxlDIwstdDMRIhwNDZJwciaMnsBYx20Z1Uqw,4063
22
+ timewise/io/stable_tap.py,sha256=DUDvUh3r2PiXZf-uxDfnCvdFtDmFsW58bCshvoafGWU,4806
23
23
  timewise/plot/__init__.py,sha256=cc00UenWC_8zAkBH-Ylhs3yCF49tAqZ2Al9MfOoXYDI,120
24
24
  timewise/plot/diagnostic.py,sha256=GRp-OUwz2yzzDu9qdViFg_e3Mxl5t1IvUJXZHuMKB2U,8276
25
25
  timewise/plot/lightcurve.py,sha256=K0UvjmvbCSsRKP3Mu9X5L5AVUwqURR76ESJCIMEgE6Q,3924
@@ -27,9 +27,9 @@ timewise/plot/panstarrs.py,sha256=X2ZULm7QT91cp4qociG0fVeI0saGLJwyKzL0141Vqis,80
27
27
  timewise/plot/sdss.py,sha256=xCNEKBWTn8SjC5-hEaTgV354laNEIGgCAxN8MwU9h5c,2554
28
28
  timewise/process/__init__.py,sha256=Yk-j1B1MnBuuaM6eFi43TxdWmFKbwFHvDsuQZt4yB_c,70
29
29
  timewise/process/config.py,sha256=d4hCvNb8JyJf2-0BTQgJaeOmHGZK_aHEDMb_xyqJgbU,1060
30
- timewise/process/interface.py,sha256=JOIh1wYuE1s9XdSfBRS7qUXexlr-p5UxdwaSjKlRZxE,5207
30
+ timewise/process/interface.py,sha256=UXgNsIec3z8boGTyMvLUzQkNIzt4OnhFQgVKtmag_Rg,5352
31
31
  timewise/process/keys.py,sha256=MGnTHM4UGUSyX7BaCzoT_dg81NEAiLCxMLBRz3Kq8yc,319
32
- timewise/process/stacking.py,sha256=vVyrhrBRpqkptNryxNxWwEvXeQLH2GYNUtUxWggYfTk,18997
32
+ timewise/process/stacking.py,sha256=9y3ZV2VW-5mv0UivfS3gjksgBr1MEtfn1ckR0r_PT4o,19032
33
33
  timewise/process/template.yml,sha256=U_xKmygDl3E-viTgZEI8pQIJwWduB52SdI2X9vy61Yo,1037
34
34
  timewise/query/__init__.py,sha256=qEVUbk20GcYOLguex1q8f0LauA2BFIWURpceuYSgMOU,327
35
35
  timewise/query/base.py,sha256=GjAoQZpaxVHcpCgPco1y5bpR0Jtd_sp_bYMI26WpAK0,1262
@@ -45,8 +45,8 @@ timewise/util/csv_utils.py,sha256=5i3Jd4c58-doPs1N_hyYZ8Uc2nvuk9nGwgPNZoNrlu0,29
45
45
  timewise/util/error_threading.py,sha256=uyV1Ri-wf87lpa17Xlp520B1V8DWHh3v9Mk97QrPmv0,2264
46
46
  timewise/util/path.py,sha256=-CcpYdjidg5FcZnRyQqrK_EKjc-7USYbJ8gtKatGl6k,254
47
47
  timewise/util/visits.py,sha256=4ZXwH7OXmp98tUPZplvuOtykB048kZoYXyuRTwQxT7w,998
48
- timewise-1.0.0a9.dist-info/METADATA,sha256=DmNUYj-hQOjxCmPRTOFPtanxTz_vy6ke4YCsvBOSImk,10367
49
- timewise-1.0.0a9.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
50
- timewise-1.0.0a9.dist-info/entry_points.txt,sha256=mYh1HsUFbV7KT8kxiGqVtR3Pk0oEk6Bd-2c5FsYVhG4,45
51
- timewise-1.0.0a9.dist-info/licenses/LICENSE,sha256=sVoNJWiTlH-NarJx0wdsob468Pg3JE6vIIgll4lCa3E,1070
52
- timewise-1.0.0a9.dist-info/RECORD,,
48
+ timewise-1.0.0a10.dist-info/METADATA,sha256=LZ_6JpaUoLJBGMcuPKqyhYcITucndg7RRqDvCFPvVPU,10831
49
+ timewise-1.0.0a10.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
50
+ timewise-1.0.0a10.dist-info/entry_points.txt,sha256=mYh1HsUFbV7KT8kxiGqVtR3Pk0oEk6Bd-2c5FsYVhG4,45
51
+ timewise-1.0.0a10.dist-info/licenses/LICENSE,sha256=sVoNJWiTlH-NarJx0wdsob468Pg3JE6vIIgll4lCa3E,1070
52
+ timewise-1.0.0a10.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.2.1
2
+ Generator: poetry-core 2.3.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any