geney 1.4.21__py2.py3-none-any.whl → 1.4.22__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.
geney/utils/SeqMats.py CHANGED
@@ -89,6 +89,25 @@ class SeqMat:
89
89
 
90
90
  self.insertion_counters = defaultdict(int)
91
91
 
92
+
93
+ def __len__(self) -> int:
94
+ return int(self.seq_array["valid_mask"].sum())
95
+
96
+ def __repr__(self):
97
+ return f"<SeqMat: {self.seq}>"
98
+
99
+ def __str__(self):
100
+ return self.seq
101
+
102
+ def get_metadata(self) -> dict:
103
+ """Retrieve all metadata as a dictionary."""
104
+ return {
105
+ "name": self.name,
106
+ "source": self.source,
107
+ "version": self.version,
108
+ "notes": self.notes
109
+ }
110
+
92
111
  @property
93
112
  def seq(self) -> str:
94
113
  return self.seq_array['nt'][self.seq_array['valid_mask']].tobytes().decode()
@@ -101,6 +120,26 @@ class SeqMat:
101
120
  def conservation(self) -> np.ndarray:
102
121
  return self.seq_array['cons'][self.seq_array['valid_mask']]
103
122
 
123
+ @property
124
+ def max_index(self) -> float:
125
+ return self.seq_array["index"].max()
126
+
127
+ @property
128
+ def min_index(self) -> float:
129
+ return self.seq_array["index"].min()
130
+
131
+ @property
132
+ def start(self) -> float:
133
+ return self.min_index
134
+
135
+ @property
136
+ def end(self) -> float:
137
+ return self.max_index
138
+
139
+ @property
140
+ def mutated_positions(self) -> np.ndarray:
141
+ return (self.seq_array["ref"] != self.seq_array["nt"])[self.seq_array["valid_mask"]].astype(int)
142
+
104
143
  def clone(self, start: Optional[float] = None, end: Optional[float] = None) -> SeqMat:
105
144
  new = SeqMat.__new__(SeqMat)
106
145
  new.name = self.name
@@ -225,3 +264,137 @@ class SeqMat:
225
264
  mask = (coords >= start) & (coords <= stop)
226
265
  return self.seq_array[mask]
227
266
  raise TypeError("Invalid index type.")
267
+
268
+ def cut_out(self, introns: List[Tuple[int, int]]) -> "SeqMat":
269
+ """
270
+ Splices out regions from the sequence corresponding to the given intron boundaries.
271
+
272
+ Handles reverse-complemented sequences by interpreting introns in reverse as well.
273
+
274
+ Args:
275
+ introns (List[Tuple[int, int]]): List of (start, end) intron boundaries.
276
+ These are always genomic (absolute) coordinates,
277
+ regardless of strand direction.
278
+
279
+ Returns:
280
+ SeqMat: A new instance with the intron regions removed.
281
+ """
282
+ # In reverse orientation, flip intron direction for comparison
283
+ if self.rev:
284
+ introns = [(end, start) if start > end else (start, end) for (start, end) in introns]
285
+
286
+ mask = np.ones(len(self.seq_array), dtype=bool)
287
+
288
+ for start, end in introns:
289
+ lo, hi = min(start, end) + 1, max(start, end) - 1
290
+ mask &= ~((self.seq_array["index"] >= lo) & (self.seq_array["index"] <= hi))
291
+
292
+ new_instance = self.clone()
293
+ new_instance.seq_array = self.seq_array[mask].copy()
294
+ return new_instance
295
+
296
+ def open_reading_frame(self, tis: int) -> "SeqMat":
297
+ """
298
+ Extracts the open reading frame starting from the translation initiation site (TIS)
299
+ until the first in-frame stop codon.
300
+
301
+ Args:
302
+ tis (int): Genomic position of the translation initiation site (start codon).
303
+
304
+ Returns:
305
+ SeqMat: A new SeqMat instance containing the ORF (from TIS to stop codon inclusive).
306
+ """
307
+ if tis not in self.seq_array["index"]:
308
+ print(f"Warning: TIS position {tis} not found, returning default.")
309
+ return self.clone(start=0, end=3)
310
+
311
+ # Extract nucleotide sequence and indices starting from TIS
312
+ mask = self.seq_array["index"] >= tis if not self.rev else self.seq_array["index"] <= tis
313
+ coding_part = self.seq_array[mask]
314
+ coding_seq = coding_part["nt"].tobytes().decode()
315
+
316
+ # Read codons in-frame
317
+ for i in range(0, len(coding_seq) - 2, 3):
318
+ codon = coding_seq[i:i + 3]
319
+ if codon in {"TAA", "TAG", "TGA"}:
320
+ # Determine index range for this ORF
321
+ start = coding_part["index"][0]
322
+ stop = coding_part["index"][i + 2]
323
+ lo, hi = sorted((start, stop))
324
+ return self.clone(start=lo, end=hi)
325
+
326
+ raise ValueError("No in-frame stop codon found after the TIS.")
327
+
328
+ def predict_splicing(self, position: int, engine='spliceai', context=7500, inplace=False): #, reference_donors=None, reference_acceptors=None) -> pd.DataFrame:
329
+ """
330
+ Predict splicing probabilities at a given position using the specified engine.
331
+
332
+ Args:
333
+ position (int): The genomic position to predict splicing probabilities for.
334
+ engine (str): The prediction engine to use. Supported: 'spliceai', 'pangolin'.
335
+ context (int): The length of the target central region (default: 7500).
336
+ format (str): Output format for the splicing engine results.
337
+
338
+ Returns:
339
+ pd.DataFrame: A DataFrame containing:
340
+ - position: The genomic position
341
+ - donor_prob: Probability of being a donor splice site
342
+ - acceptor_prob: Probability of being an acceptor splice site
343
+ - nucleotides: The nucleotide sequence at that position
344
+
345
+ Raises:
346
+ ValueError: If an unsupported engine is provided.
347
+ IndexError: If the position is not found in the sequence.
348
+ """
349
+ # Retrieve extended context (includes flanks) around the position.
350
+ # seq, indices = self.get_context(position, context=context, padding='N')
351
+ target = self.clone(position - context, position + context)
352
+ # print(len(target.seq))
353
+ seq, indices = target.seq, target.index
354
+ # print(len(seq))
355
+ # rel_pos = np.where(indices == position)[0][0]
356
+ # print(rel_pos)
357
+ rel_pos = np.abs(indices - position).argmin()
358
+ # print(rel_pos, len(seq))
359
+ left_missing, right_missing = max(0, context - rel_pos), max(0, context - (len(seq) - rel_pos))
360
+ # print(left_missing, right_missing)
361
+ if left_missing > 0 or right_missing > 0:
362
+ step = -1 if self.rev else 1
363
+
364
+ if left_missing > 0:
365
+ left_pad = np.arange(indices[0] - step * left_missing, indices[0], step)
366
+ else:
367
+ left_pad = np.array([], dtype=indices.dtype)
368
+
369
+ if right_missing > 0:
370
+ right_pad = np.arange(indices[-1] + step, indices[-1] + step * (right_missing + 1), step)
371
+ else:
372
+ right_pad = np.array([], dtype=indices.dtype)
373
+
374
+ seq = 'N' * left_missing + seq + 'N' * right_missing
375
+ indices = np.concatenate([left_pad, indices, right_pad])
376
+
377
+ # Run the splicing prediction engine (function assumed to be defined externally)
378
+ from .splicing_utils import run_splicing_engine
379
+ donor_probs, acceptor_probs = run_splicing_engine(seq, engine)
380
+ # Trim off the fixed flanks before returning results.
381
+ seq = seq[5000:-5000]
382
+ indices = indices[5000:-5000]
383
+ df = pd.DataFrame({
384
+ 'position': indices,
385
+ 'donor_prob': donor_probs,
386
+ 'acceptor_prob': acceptor_probs,
387
+ 'nucleotides': list(seq)
388
+ }).set_index('position').round(3)
389
+ # if reference_donors is not None:
390
+ # df['ref_donor'] = df.index.isin(reference_donors).astype(int)
391
+ # if reference_acceptors is not None:
392
+ # df['ref_acceptor'] = df.index.isin(reference_acceptors).astype(int)
393
+
394
+ df.attrs['name'] = self.name
395
+ if inplace:
396
+ self.predicted_splicing = df
397
+ return self
398
+ else:
399
+ return df
400
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geney
3
- Version: 1.4.21
3
+ Version: 1.4.22
4
4
  Summary: A Python package for gene expression modeling.
5
5
  Home-page: https://github.com/nicolaslynn/geney
6
6
  Author: Nicolas Lynn
@@ -37,7 +37,7 @@ geney/translation_initiation/tis_utils.py,sha256=AF3siFjuQH-Rs44EV-80zHdbxRMvN4w
37
37
  geney/translation_initiation/resources/kozak_pssm.json,sha256=pcd0Olziutq-6H3mFWDCD9cujQ_AlZO-iiOvBl82hqE,1165
38
38
  geney/translation_initiation/resources/tis_regressor_model.joblib,sha256=IXb4DUDhJ5rBDKcqMk9zE3ECTZZcdj7Jixz3KpoZ7OA,2592025
39
39
  geney/utils/Fasta_segment.py,sha256=weB5NJ65P0XiyAJCiCHx4T9sHC1pWLpuQeOy0B85gyg,11364
40
- geney/utils/SeqMats.py,sha256=q858gWPsSoS4HUr6FD1CHYuUh5AE5u9KePHYT7FQw7g,8777
40
+ geney/utils/SeqMats.py,sha256=Hneqxz92WFrHi0lyHs2ZwTd091TtFclgybcvtUCktJA,15689
41
41
  geney/utils/SeqMatsOld.py,sha256=syRU5DAuTh3xUfGW_qP9wlcBO5pHsG_y5PlrfXTIxUY,18502
42
42
  geney/utils/TranscriptLibrary.py,sha256=ma_ZVPgglxXDDneEvdqxxeqxG8eSFL-zgLUXyC6BqY8,2070
43
43
  geney/utils/__init__.py,sha256=-nJ-DMx1JzP-ZCe_QuQCeM0ZYIT_16jxoXDhUaO_4Oc,714
@@ -46,7 +46,7 @@ geney/utils/pangolin_utils.py,sha256=JQSPbWxdzqGFYfWQktkfLMaMSGR28eGQhNzO7MLMe5M
46
46
  geney/utils/spliceai_utils.py,sha256=VtrIbjyQxk_3lw86eWjftRYyal9OzxArJ0GV5u_ymTg,2721
47
47
  geney/utils/splicing_utils.py,sha256=vPCGnCPR1ooEZEHR79yFHLmRQXEJHXEQjjxpBR-YWOs,20635
48
48
  geney/utils/utils.py,sha256=m51Vd0cEbrcIHo6_8BAuI9YSPcKRs22e5LfVd2Qj6Is,2181
49
- geney-1.4.21.dist-info/METADATA,sha256=m-32P-otBh8Nj1P_rBrqgE6wYPEA04pcTV1tGxuTkWM,990
50
- geney-1.4.21.dist-info/WHEEL,sha256=AHX6tWk3qWuce7vKLrj7lnulVHEdWoltgauo8bgCXgU,109
51
- geney-1.4.21.dist-info/top_level.txt,sha256=O-FuNUMb5fn9dhZ-dYCgF0aZtfi1EslMstnzhc5IIVo,6
52
- geney-1.4.21.dist-info/RECORD,,
49
+ geney-1.4.22.dist-info/METADATA,sha256=OH6exXPW8_IdusLX5g-xeLBXyyQx1DQyfZeguHjvyQY,990
50
+ geney-1.4.22.dist-info/WHEEL,sha256=AHX6tWk3qWuce7vKLrj7lnulVHEdWoltgauo8bgCXgU,109
51
+ geney-1.4.22.dist-info/top_level.txt,sha256=O-FuNUMb5fn9dhZ-dYCgF0aZtfi1EslMstnzhc5IIVo,6
52
+ geney-1.4.22.dist-info/RECORD,,
File without changes