pylocuszoom 0.1.0__py3-none-any.whl → 0.2.0__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.
@@ -22,7 +22,7 @@ from .logging import logger
22
22
  RECOMB_COLOR = "#7FCDFF" # Light blue
23
23
 
24
24
  # Data sources by species
25
- DOG_RECOMB_URL = (
25
+ CANINE_RECOMB_URL = (
26
26
  "https://github.com/cflerin/dog_recombination/raw/master/dog_genetic_maps.tar.gz"
27
27
  )
28
28
 
@@ -177,11 +177,11 @@ def get_default_data_dir() -> Path:
177
177
  return base / "snp-scope-plot" / "recombination_maps"
178
178
 
179
179
 
180
- def download_dog_recombination_maps(
180
+ def download_canine_recombination_maps(
181
181
  output_dir: Optional[str] = None,
182
182
  force: bool = False,
183
183
  ) -> Path:
184
- """Download dog recombination rate maps from Campbell et al. 2016.
184
+ """Download canine recombination rate maps from Campbell et al. 2016.
185
185
 
186
186
  Downloads from: https://github.com/cflerin/dog_recombination
187
187
 
@@ -213,22 +213,22 @@ def download_dog_recombination_maps(
213
213
  # Create output directory
214
214
  output_path.mkdir(parents=True, exist_ok=True)
215
215
 
216
- logger.info("Downloading dog recombination maps from GitHub...")
217
- logger.debug(f"Source: {DOG_RECOMB_URL}")
216
+ logger.info("Downloading canine recombination maps from GitHub...")
217
+ logger.debug(f"Source: {CANINE_RECOMB_URL}")
218
218
 
219
219
  with tempfile.TemporaryDirectory() as tmpdir:
220
220
  # Download tar.gz file
221
221
  tar_path = Path(tmpdir) / "dog_genetic_maps.tar.gz"
222
222
 
223
223
  try:
224
- urllib.request.urlretrieve(DOG_RECOMB_URL, tar_path)
224
+ urllib.request.urlretrieve(CANINE_RECOMB_URL, tar_path)
225
225
  except Exception as e:
226
226
  logger.debug(f"urllib download failed: {e}")
227
227
  logger.debug("Trying alternative method with requests...")
228
228
  try:
229
229
  import requests
230
230
 
231
- response = requests.get(DOG_RECOMB_URL, timeout=60)
231
+ response = requests.get(CANINE_RECOMB_URL, timeout=60)
232
232
  response.raise_for_status()
233
233
  tar_path.write_bytes(response.content)
234
234
  except ImportError:
@@ -282,14 +282,14 @@ def download_dog_recombination_maps(
282
282
 
283
283
  def load_recombination_map(
284
284
  chrom: int,
285
- species: str = "dog",
285
+ species: str = "canine",
286
286
  data_dir: Optional[str] = None,
287
287
  ) -> pd.DataFrame:
288
288
  """Load recombination map for a specific chromosome.
289
289
 
290
290
  Args:
291
- chrom: Chromosome number (1-38 for dog, 1-18 for cat) or 'X'.
292
- species: Species name ('dog', 'cat').
291
+ chrom: Chromosome number (1-38 for canine, 1-18 for feline) or 'X'.
292
+ species: Species name ('canine', 'feline').
293
293
  data_dir: Directory containing recombination maps.
294
294
 
295
295
  Returns:
@@ -326,7 +326,7 @@ def get_recombination_rate_for_region(
326
326
  chrom: int,
327
327
  start: int,
328
328
  end: int,
329
- species: str = "dog",
329
+ species: str = "canine",
330
330
  data_dir: Optional[str] = None,
331
331
  genome_build: Optional[str] = None,
332
332
  ) -> pd.DataFrame:
@@ -336,7 +336,7 @@ def get_recombination_rate_for_region(
336
336
  chrom: Chromosome number.
337
337
  start: Start position (bp).
338
338
  end: End position (bp).
339
- species: Species name ('dog', 'cat').
339
+ species: Species name ('canine', 'feline').
340
340
  data_dir: Directory containing recombination maps.
341
341
  genome_build: Target genome build (e.g., "canfam4"). If specified and
342
342
  different from source data (CanFam3.1), coordinates are lifted over.
@@ -345,7 +345,7 @@ def get_recombination_rate_for_region(
345
345
  DataFrame with pos and rate columns for the region.
346
346
 
347
347
  Note:
348
- Built-in dog recombination maps are in CanFam3.1 coordinates.
348
+ Built-in canine recombination maps are in CanFam3.1 coordinates.
349
349
  If genome_build="canfam4", positions are automatically lifted over.
350
350
  This requires pyliftover: pip install pyliftover
351
351
  """
@@ -353,7 +353,7 @@ def get_recombination_rate_for_region(
353
353
 
354
354
  # Liftover if needed
355
355
  build = _normalize_build(genome_build)
356
- if species == "dog" and build == "canfam4":
356
+ if species == "canine" and build == "canfam4":
357
357
  logger.debug(f"Lifting over recombination map for chr{chrom} to CanFam4")
358
358
  df = liftover_recombination_map(
359
359
  df, from_build="canfam3", to_build="canfam4", chrom=chrom
pylocuszoom/utils.py CHANGED
@@ -29,7 +29,9 @@ def is_spark_dataframe(df: Any) -> bool:
29
29
  True if PySpark DataFrame, False otherwise.
30
30
  """
31
31
  # Check class name to avoid importing pyspark
32
- return type(df).__name__ == "DataFrame" and type(df).__module__.startswith("pyspark")
32
+ return type(df).__name__ == "DataFrame" and type(df).__module__.startswith(
33
+ "pyspark"
34
+ )
33
35
 
34
36
 
35
37
  def to_pandas(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pylocuszoom
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Regional association plots for GWAS results with LD coloring, gene tracks, and recombination rate overlays
5
5
  Project-URL: Homepage, https://github.com/michael-denyer/pylocuszoom
6
6
  Project-URL: Documentation, https://github.com/michael-denyer/pylocuszoom#readme
@@ -71,6 +71,8 @@ Inspired by [LocusZoom](http://locuszoom.org/) and [locuszoomr](https://github.c
71
71
  - **eQTL overlay**: Expression QTL data as separate panel
72
72
  - **PySpark support**: Handles large-scale genomics DataFrames
73
73
 
74
+ ![Example regional association plot](examples/regional_plot.png)
75
+
74
76
  ## Installation
75
77
 
76
78
  ```bash
@@ -88,8 +90,8 @@ pip install pylocuszoom
88
90
  ```python
89
91
  from pylocuszoom import LocusZoomPlotter
90
92
 
91
- # Initialize plotter (loads reference data for dog)
92
- plotter = LocusZoomPlotter(species="dog")
93
+ # Initialize plotter (loads reference data for canine)
94
+ plotter = LocusZoomPlotter(species="canine")
93
95
 
94
96
  # Create regional plot
95
97
  fig = plotter.plot(
@@ -109,7 +111,7 @@ fig.savefig("regional_plot.png", dpi=150)
109
111
  from pylocuszoom import LocusZoomPlotter
110
112
 
111
113
  plotter = LocusZoomPlotter(
112
- species="dog", # or "cat", or None for custom
114
+ species="canine", # or "feline", or None for custom
113
115
  plink_path="/path/to/plink", # Optional, auto-detects if on PATH
114
116
  )
115
117
 
@@ -134,10 +136,10 @@ fig = plotter.plot(
134
136
 
135
137
  ## Genome Builds
136
138
 
137
- The default genome build for dog is CanFam3.1. For CanFam4 data:
139
+ The default genome build for canine is CanFam3.1. For CanFam4 data:
138
140
 
139
141
  ```python
140
- plotter = LocusZoomPlotter(species="dog", genome_build="canfam4")
142
+ plotter = LocusZoomPlotter(species="canine", genome_build="canfam4")
141
143
  ```
142
144
 
143
145
  Recombination maps are automatically lifted over from CanFam3.1 to CanFam4 coordinates using the UCSC liftOver chain file.
@@ -145,8 +147,8 @@ Recombination maps are automatically lifted over from CanFam3.1 to CanFam4 coord
145
147
  ## Using with Other Species
146
148
 
147
149
  ```python
148
- # Cat (LD and gene tracks, user provides recombination data)
149
- plotter = LocusZoomPlotter(species="cat")
150
+ # Feline (LD and gene tracks, user provides recombination data)
151
+ plotter = LocusZoomPlotter(species="feline")
150
152
 
151
153
  # Custom species (provide all reference data)
152
154
  plotter = LocusZoomPlotter(
@@ -163,27 +165,20 @@ fig = plotter.plot(
163
165
  )
164
166
  ```
165
167
 
166
- ## Interactive Backends
168
+ ## Interactive Backends (Coming Soon)
167
169
 
168
- Choose between static (matplotlib) and interactive (plotly, bokeh) outputs:
170
+ > **Note:** Interactive backends (plotly, bokeh) are planned but not yet fully integrated. Currently all plots use matplotlib.
169
171
 
170
172
  ```python
171
- # Static publication-quality plot (default)
172
- plotter = LocusZoomPlotter(species="dog", backend="matplotlib")
173
+ # Static publication-quality plot (default, currently only supported backend)
174
+ plotter = LocusZoomPlotter(species="canine", backend="matplotlib")
173
175
  fig = plotter.plot(gwas_df, chrom=1, start=1000000, end=2000000)
174
176
  fig.savefig("plot.png", dpi=150)
175
-
176
- # Interactive with plotly (hover tooltips, zoom/pan)
177
- plotter = LocusZoomPlotter(species="dog", backend="plotly")
178
- fig = plotter.plot(gwas_df, chrom=1, start=1000000, end=2000000)
179
- fig.write_html("plot.html")
180
-
181
- # Interactive with bokeh (dashboard-friendly)
182
- plotter = LocusZoomPlotter(species="dog", backend="bokeh")
183
- fig = plotter.plot(gwas_df, chrom=1, start=1000000, end=2000000)
184
177
  ```
185
178
 
186
- Interactive plots show SNP details (RS ID, p-value, R²) on hover.
179
+ Future releases will support:
180
+ - **Plotly**: Interactive plots with hover tooltips, zoom/pan
181
+ - **Bokeh**: Dashboard-friendly interactive plots
187
182
 
188
183
  ## Stacked Plots
189
184
 
@@ -324,14 +319,14 @@ chr pos rate cM
324
319
 
325
320
  ## Reference Data
326
321
 
327
- Dog recombination maps are downloaded from [Campbell et al. 2016](https://github.com/cflerin/dog_recombination) on first use.
322
+ Canine recombination maps are downloaded from [Campbell et al. 2016](https://github.com/cflerin/dog_recombination) on first use.
328
323
 
329
324
  To manually download:
330
325
 
331
326
  ```python
332
- from pylocuszoom import download_dog_recombination_maps
327
+ from pylocuszoom import download_canine_recombination_maps
333
328
 
334
- download_dog_recombination_maps()
329
+ download_canine_recombination_maps()
335
330
  ```
336
331
 
337
332
  ## Logging
@@ -0,0 +1,21 @@
1
+ pylocuszoom/__init__.py,sha256=f8h22YYL3JkDP5P_dJftu98qlJkXvaAeyto5kVc8bzU,3785
2
+ pylocuszoom/colors.py,sha256=XXTCmCFfHrOrSiP6b0V8Kis7Z1tyvGEKJpdv59QDVQ8,6610
3
+ pylocuszoom/eqtl.py,sha256=9lZJ8jT1WEj3won6D9B54xdqUvbRvxpOitf97NCUR28,6167
4
+ pylocuszoom/finemapping.py,sha256=IZEEF13m8xD2qfnTsqcv67BtPAvqC_FrXdGv1VG8BHk,6351
5
+ pylocuszoom/gene_track.py,sha256=ZYAWOUHOo9oieovl7VHGCB3j_HBbnr5wwtIwxozgRhE,10854
6
+ pylocuszoom/labels.py,sha256=Ams5WVZFNVT692BRiQ5wZcdbdNEAm5xtgRwmF5u0s_A,3492
7
+ pylocuszoom/ld.py,sha256=64xIulpDVvbMSryWUPoCQ99Odcjwf1wejpwVr_30MLU,6412
8
+ pylocuszoom/logging.py,sha256=nZHEkbnjp8zoyWj_S-Hy9UQvUYLoMoxyiOWRozBT2dg,4987
9
+ pylocuszoom/plotter.py,sha256=sPqK74B9-ldcKhrrWixyapIdQ4dVgFRERZfJw4ZNS5Y,37865
10
+ pylocuszoom/recombination.py,sha256=Q2tAft54nJWHlZt-vZje1r_5RP7D8_VUy5ab_deYXVw,13749
11
+ pylocuszoom/utils.py,sha256=fKNX9WSTbfHR1EpPYijt6ycNjXEjwzunQMHXAvHaK3s,5211
12
+ pylocuszoom/backends/__init__.py,sha256=7dlGvDoqMVK3fCtoMcI9zOP9qO0odQGPwfXhxnLfXfI,1196
13
+ pylocuszoom/backends/base.py,sha256=4EGT4_88y2jvhWm1zAal9v9yuaHhCLo7-rchcWmIK8c,8451
14
+ pylocuszoom/backends/bokeh_backend.py,sha256=V0yQi1lY96hjTjBXGJtLKGy1LFNii58kTAJiqu0LYPg,12900
15
+ pylocuszoom/backends/matplotlib_backend.py,sha256=yTTm9KG7e0ct-mvHk_tfJX6SOL97pABsJzs4Xn6H1zw,8010
16
+ pylocuszoom/backends/plotly_backend.py,sha256=2EDJZczqjZ5gItd3Fb4UaRYGj7SQy7Wgg5UIL8LJ9LM,14128
17
+ pylocuszoom/reference_data/__init__.py,sha256=qqHqAUt1jebGlCN3CjqW3Z-_coHVNo5K3a3bb9o83hA,109
18
+ pylocuszoom-0.2.0.dist-info/METADATA,sha256=tDPRbhg4r1NavMCH1e_VTzKY9qApsY97yyiEYh04S78,11723
19
+ pylocuszoom-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
20
+ pylocuszoom-0.2.0.dist-info/licenses/LICENSE.md,sha256=U2y_hv8RcN5lECA3uK88irU3ODUE1TDAPictcmnP0Q4,698
21
+ pylocuszoom-0.2.0.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- pylocuszoom/__init__.py,sha256=1TUI6bxbsPbNYrJR1-i_cffbh7mqYrXfFuUdF4r4sl8,3174
2
- pylocuszoom/colors.py,sha256=VnQJEgC6uEBqjlu9mq16ijNn9gRwWHZEAqpu1E-KVug,2638
3
- pylocuszoom/eqtl.py,sha256=GHOcSs2LRa4YHiKUm-ZNHQz5aR7z-5f8nRFpLvn8ezk,6154
4
- pylocuszoom/gene_track.py,sha256=2U9JawzPfcjtQo_FhMMTw5juY8QQwRE6mTXy_JdChq4,10281
5
- pylocuszoom/labels.py,sha256=PhplRqGa1G_4A1JZRdIa5ufnnkfLjpBoln-bs8IL7ok,3585
6
- pylocuszoom/ld.py,sha256=Jwh_wi34IJMiaXBkNKPTL7S-YVEJXJfckJazSKN3ZBc,6282
7
- pylocuszoom/logging.py,sha256=nZHEkbnjp8zoyWj_S-Hy9UQvUYLoMoxyiOWRozBT2dg,4987
8
- pylocuszoom/plotter.py,sha256=B_5O5sXqln2oPUU2Nx8t8IRbqka7AzGfisH1fLorDpg,26991
9
- pylocuszoom/recombination.py,sha256=qZHghHBnQLfaADo1PfGPGhRXuyaA5YZM8wI9FLnpfEk,13698
10
- pylocuszoom/utils.py,sha256=1I4r9KOd8yje12L0Y7GiX2Adc7Qrefq5VqdHv83KM7g,5197
11
- pylocuszoom/backends/__init__.py,sha256=DpPzFMe43FiZv3olsNTmb00il-sqdb6bKlDmFsQrnxY,1320
12
- pylocuszoom/backends/base.py,sha256=CBubNWuP3qyovOXoseaf3a6CwsDQbujXy-HOTnHJYmE,8457
13
- pylocuszoom/backends/bokeh_backend.py,sha256=4H_ay8jaWIVZtlyXGiPpm9sNmGMoF11U56ZjUqaL9YQ,12984
14
- pylocuszoom/backends/matplotlib_backend.py,sha256=tThkVE-49nyKJYR5_qUPu2svk4LVR3HpP2Ac90FT3sw,7907
15
- pylocuszoom/backends/plotly_backend.py,sha256=3-s3k93KgTzEKQJWcSb_NKGKzuKb3pLR3DEaUjOzJe8,14202
16
- pylocuszoom/reference_data/__init__.py,sha256=qqHqAUt1jebGlCN3CjqW3Z-_coHVNo5K3a3bb9o83hA,109
17
- pylocuszoom-0.1.0.dist-info/METADATA,sha256=k7iSnBOEKvDhzafDZjIjtuIOB5KefGy981kFyLXLEiM,11828
18
- pylocuszoom-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
19
- pylocuszoom-0.1.0.dist-info/licenses/LICENSE.md,sha256=U2y_hv8RcN5lECA3uK88irU3ODUE1TDAPictcmnP0Q4,698
20
- pylocuszoom-0.1.0.dist-info/RECORD,,