timewise 0.4.4__tar.gz → 0.4.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: timewise
3
- Version: 0.4.4
3
+ Version: 0.4.7
4
4
  Summary: A small package to download infrared data from the WISE satellite
5
5
  Home-page: https://github.com/JannisNe/timewise
6
6
  License: MIT
@@ -15,6 +15,8 @@ Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Requires-Dist: astropy (>=5.1,<6.0)
17
17
  Requires-Dist: backoff (>=2.1.2,<3.0.0)
18
+ Requires-Dist: jupyter[jupyter] (>=1.0.0,<2.0.0)
19
+ Requires-Dist: jupyterlab[jupyter] (>=4.0.6,<5.0.0)
18
20
  Requires-Dist: matplotlib (>=3.5.3,<4.0.0)
19
21
  Requires-Dist: numpy (>=1.23.2,<2.0.0)
20
22
  Requires-Dist: pandas (>=1.4.3,<3.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "timewise"
3
- version = "0.4.4"
3
+ version = "0.4.7"
4
4
  description = "A small package to download infrared data from the WISE satellite"
5
5
  authors = ["Jannis Necker <jannis.necker@gmail.com>"]
6
6
  license = "MIT"
@@ -30,6 +30,8 @@ seaborn = ">=0.11.2,<0.13.0"
30
30
  urllib3 = "1.26.15"
31
31
  pydantic = ">=1.9.0,<2.0.0"
32
32
  scikit-learn = "^1.3.0"
33
+ jupyterlab = {version = "^4.0.6", extras = ["jupyter"]}
34
+ jupyter = {version = "^1.0.0", extras = ["jupyter"]}
33
35
 
34
36
  [tool.poetry.dev-dependencies]
35
37
  coveralls = "^3.3.1"
@@ -39,7 +41,7 @@ pytest = "^7.2.2"
39
41
  optional = true
40
42
 
41
43
  [tool.poetry.group.docs.dependencies]
42
- myst-parser = "^1.0.0"
44
+ myst-parser = ">=1,<3"
43
45
  sphinx-rtd-theme = "^1.3.0"
44
46
 
45
47
 
@@ -2,4 +2,4 @@ from timewise.wise_data_by_visit import WiseDataByVisit
2
2
  from timewise.wise_bigdata_desy_cluster import WISEDataDESYCluster
3
3
  from timewise.parent_sample_base import ParentSampleBase
4
4
 
5
- __version__ = "0.4.4"
5
+ __version__ = "0.4.5"
@@ -131,7 +131,8 @@ class WISEDataDESYCluster(WiseDataByVisit):
131
131
  chunk_number=None,
132
132
  jobID=None,
133
133
  return_filename=False,
134
- use_bigdata_dir=False
134
+ use_bigdata_dir=False,
135
+ verify_contains_lightcurves=False
135
136
  ):
136
137
  fn = self._data_product_filename(
137
138
  service,
@@ -144,6 +145,13 @@ class WISEDataDESYCluster(WiseDataByVisit):
144
145
  try:
145
146
  with gzip.open(fn, 'rt', encoding="utf-8") as fzip:
146
147
  data_product = json.load(fzip)
148
+
149
+ if verify_contains_lightcurves:
150
+ try:
151
+ self._verify_contains_lightcurves(data_product)
152
+ except KeyError as e:
153
+ raise KeyError(f"{fn}: {e}")
154
+
147
155
  if return_filename:
148
156
  return data_product, fn
149
157
  return data_product
@@ -725,7 +725,21 @@ class WISEDataBase(abc.ABC):
725
725
  else:
726
726
  return os.path.join(self._cache_photometry_dir, fn + f"_{jobID}.json")
727
727
 
728
- def load_data_product(self, service, chunk_number=None, jobID=None, return_filename=False):
728
+ @staticmethod
729
+ def _verify_contains_lightcurves(data_product):
730
+ mask = ["timewise_lightcurve" in data.keys() for data in data_product.values()]
731
+ if not any(mask):
732
+ raise KeyError(f"'timewise_lightcurves' in none of the results."
733
+ f"Cluster job probably did not finish.")
734
+
735
+ def load_data_product(
736
+ self,
737
+ service,
738
+ chunk_number=None,
739
+ jobID=None,
740
+ return_filename=False,
741
+ verify_contains_lightcurves=False
742
+ ):
729
743
  """
730
744
  Load data product from disk
731
745
 
@@ -736,12 +750,22 @@ class WISEDataBase(abc.ABC):
736
750
  :param jobID: jobID to load, if None load the combined file for this chunk
737
751
  :type jobID: int, optional
738
752
  :param return_filename: return filename of data product, defaults to False
753
+ :type return_filename: bool, optional
754
+ :param verify_contains_lightcurves: verify that the data product contains lightcurves, defaults to False
755
+ :type verify_contains_lightcurves: bool, optional
739
756
  """
740
757
  fn = self._data_product_filename(service, chunk_number, jobID)
741
758
  logger.debug(f"loading {fn}")
742
759
  try:
743
760
  with open(fn, "r") as f:
744
761
  lcs = json.load(f)
762
+
763
+ if verify_contains_lightcurves:
764
+ try:
765
+ self._verify_contains_lightcurves(lcs)
766
+ except KeyError as e:
767
+ raise KeyError(f"{fn}: {e}")
768
+
745
769
  if return_filename:
746
770
  return lcs, fn
747
771
  return lcs
@@ -791,33 +815,43 @@ class WISEDataBase(abc.ABC):
791
815
 
792
816
  lcs = None
793
817
  fns = list()
794
- missing_files = 0
818
+ missing_files = False
819
+ erroneous_files = False
795
820
  for i in itr[1]:
796
821
  kw = dict(kwargs)
797
822
  kw[itr[0]] = i
798
823
  kw['return_filename'] = True
799
- res = self.load_data_product(**kw)
824
+ kw["verify_contains_lightcurves"] = True
825
+
826
+ try:
827
+ res = self.load_data_product(**kw)
828
+ if res is not None:
829
+ ilcs, ifn = res
830
+ fns.append(ifn)
831
+ if isinstance(lcs, type(None)):
832
+ lcs = dict(ilcs)
833
+ else:
834
+ lcs.update(ilcs)
800
835
 
801
- if not isinstance(res, type(None)):
802
- ilcs, ifn = res
803
- fns.append(ifn)
804
- if isinstance(lcs, type(None)):
805
- lcs = dict(ilcs)
806
836
  else:
807
- lcs.update(ilcs)
837
+ missing_files = True
808
838
 
809
- else:
810
- missing_files += 1
811
-
812
- if missing_files > 0:
813
- msg = f"Missing {missing_files} for {service}"
814
- if chunk_number is not None:
815
- msg += f" chunk {chunk_number}"
816
- msg += "! Not saving data product"
817
- logger.warning(msg)
839
+ except KeyError as e:
840
+ logger.error(e)
841
+ erroneous_files = True
842
+
843
+ if missing_files:
844
+ logger.warning(f"Missing files for {service}")
845
+
846
+ if erroneous_files:
847
+ logger.warning(f"Erroneous files for {service}")
848
+
849
+ if erroneous_files or missing_files:
850
+ _chunk_str = f" for chunk {chunk_number}" if chunk_number is not None else ""
851
+ logger.warning(f"Not saving combined data product{_chunk_str}")
818
852
  break
819
853
 
820
- if missing_files == 0:
854
+ if not (erroneous_files or missing_files):
821
855
  self._save_data_product(lcs, service=service, chunk_number=chunk_number, overwrite=overwrite)
822
856
 
823
857
  if remove:
@@ -1659,7 +1693,7 @@ class WISEDataBase(abc.ABC):
1659
1693
 
1660
1694
  if return_all:
1661
1695
  return_closest_allwise_mask = list(closest_allwise_mask) if closest_allwise_mask is not None else None
1662
- return list(bad_indices), cluster_res, return_closest_allwise_mask
1696
+ return list(bad_indices), cluster_res, data_mask, return_closest_allwise_mask
1663
1697
  else:
1664
1698
  return list(bad_indices)
1665
1699
 
@@ -4,6 +4,7 @@ import numpy as np
4
4
  import logging
5
5
  from scipy import stats
6
6
  import matplotlib.pyplot as plt
7
+ from matplotlib.lines import Line2D
7
8
 
8
9
  from timewise.wise_data_base import WISEDataBase
9
10
  from timewise.utils import get_excess_variance
@@ -499,7 +500,7 @@ class WiseDataByVisit(WISEDataBase):
499
500
 
500
501
  # get a mask indicating outliers based on position
501
502
  ra, dec = pos.astype(float)
502
- bad_indices_position, cluster_res, allwise_mask = self.calculate_position_mask(
503
+ bad_indices_position, cluster_res, data_mask, allwise_mask = self.calculate_position_mask(
503
504
  lightcurve, ra=ra, dec=dec, return_all=True, whitelist_region=self.whitelist_region.to("arcsec").value
504
505
  )
505
506
  position_mask = (
@@ -537,8 +538,7 @@ class WiseDataByVisit(WISEDataBase):
537
538
  )
538
539
 
539
540
  # set markers for visits
540
- markers = ['o', 'v', '^', '<', '>', '1', '2', '3', '4', '8', 's', 'p', '*', 'h', 'H', '+', 'x', 'D', 'd', '|',
541
- '_', 'P', 'X']
541
+ markers = list(Line2D.filled_markers) + ["$1$", "$2$", "$3$", "$4$", "$5$", "$6$", "$7$", "$8$", "$9$"]
542
542
 
543
543
  # calculate ra and dec relative to center of cutout
544
544
  ra = (lightcurve.ra - pos[self.parent_sample.default_keymap["ra"]]) * 3600
@@ -547,41 +547,65 @@ class WiseDataByVisit(WISEDataBase):
547
547
  # for each visit plot the datapoints on the cutout
548
548
  for visit in np.unique(visit_map):
549
549
  m = visit_map == visit
550
-
551
550
  label = str(visit)
552
- marker = markers[visit]
553
- color = f"C{visit}"
551
+ axs[0].plot([], [], marker=markers[visit], label=label, mec="k", mew=1, mfc="none", ls="")
554
552
 
555
- for im, _color, _label, zorder in zip(
553
+ for im, mec, zorder in zip(
556
554
  [position_mask, ~position_mask],
557
- [color, "gray"],
558
- [label, ""],
555
+ ["k", "none"],
559
556
  [1, 0]
560
557
  ):
561
558
  mask = m & im
562
- datapoints = lightcurve[mask]
563
- if ("sigra" in datapoints.columns) and ("sigdec" in datapoints.columns):
564
- has_sig = ~datapoints.sigra.isna() & ~datapoints.sigdec.isna()
565
- axs[0].errorbar(
566
- ra[mask][has_sig],
567
- dec[mask][has_sig],
568
- xerr=datapoints.sigra[has_sig] / 3600,
569
- yerr=datapoints.sigdec[has_sig] / 3600,
570
- label=_label,
571
- marker=marker,
572
- ls="",
573
- color=_color,
574
- zorder=zorder
575
- )
576
- axs[0].scatter(
577
- ra[mask][~has_sig],
578
- dec[mask][~has_sig],
579
- marker=marker,
580
- color=_color,
581
- zorder=zorder
559
+
560
+ for i_data_mask, i_data in zip([data_mask, ~data_mask], ["data", "other_allwise"]):
561
+ datapoints = lightcurve[mask & i_data_mask]
562
+ cluster_labels = (
563
+ cluster_res.labels_[mask[i_data_mask]] if i_data == "data"
564
+ else np.array([-1] * len(datapoints))
582
565
  )
583
- else:
584
- axs[0].scatter(ra[mask], dec[mask], label=_label, marker=marker, color=_color, zorder=zorder)
566
+
567
+ for cluster_label in np.unique(cluster_labels):
568
+ cluster_label_mask = cluster_labels == cluster_label
569
+ datapoints_cluster = datapoints[cluster_label_mask]
570
+ # make a marker for the visit and colored by cluster
571
+ color = f"C{cluster_label}" if cluster_label != -1 else "grey"
572
+
573
+ if ("sigra" in datapoints_cluster.columns) and ("sigdec" in datapoints_cluster.columns):
574
+ has_sig = ~datapoints_cluster.sigra.isna() & ~datapoints_cluster.sigdec.isna()
575
+ _ra = ra[mask & i_data_mask][cluster_label_mask]
576
+ _dec = dec[mask & i_data_mask][cluster_label_mask]
577
+
578
+ axs[0].errorbar(
579
+ _ra[has_sig],
580
+ _dec[has_sig],
581
+ xerr=datapoints_cluster.sigra[has_sig] / 3600,
582
+ yerr=datapoints_cluster.sigdec[has_sig] / 3600,
583
+ marker=markers[visit],
584
+ ls="",
585
+ color=color,
586
+ zorder=zorder,
587
+ ms=10,
588
+ mec=mec,
589
+ mew=0.1
590
+ )
591
+ axs[0].scatter(
592
+ _ra[~has_sig],
593
+ _dec[~has_sig],
594
+ marker=markers[visit],
595
+ color=color,
596
+ zorder=zorder,
597
+ edgecolors=mec,
598
+ linewidths=0.1,
599
+ )
600
+ else:
601
+ axs[0].scatter(
602
+ ra[mask], dec[mask],
603
+ marker=markers[visit],
604
+ color=color,
605
+ zorder=zorder,
606
+ edgecolors=mec,
607
+ linewidths=0.1,
608
+ )
585
609
 
586
610
  # for each band indicate the outliers based on brightness with circles
587
611
  for b, outlier_mask in outlier_masks.items():
File without changes
File without changes
File without changes
File without changes
File without changes