yinuozhang commited on
Commit
3226415
1 Parent(s): 4f0aaef

add more functions

Browse files
Files changed (1) hide show
  1. app.py +107 -26
app.py CHANGED
@@ -327,25 +327,44 @@ def annotate_cyclic_structure(mol, sequence):
327
 
328
  return img
329
 
330
- def create_linear_peptide_viz(sequence):
331
  """
332
- Create a linear representation of peptide with residue annotations
 
333
  """
334
- # Create figure and axis
335
- fig, ax = plt.subplots(figsize=(15, 5))
336
- ax.set_xlim(0, 10)
337
- ax.set_ylim(0, 2)
 
338
 
339
- # Parse sequence to get residues
340
  if sequence.startswith('cyclo('):
341
- residues = sequence[6:-1].split('-') # Remove cyclo() and split
342
  else:
343
  residues = sequence.split('-')
344
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  num_residues = len(residues)
346
- spacing = 9.0 / (num_residues - 1) # Leave margins on sides
347
 
348
- # Draw peptide backbone
349
  y_pos = 1.5
350
  for i in range(num_residues):
351
  x_pos = 0.5 + i * spacing
@@ -353,30 +372,92 @@ def create_linear_peptide_viz(sequence):
353
  # Draw amino acid box
354
  rect = patches.Rectangle((x_pos-0.3, y_pos-0.2), 0.6, 0.4,
355
  facecolor='lightblue', edgecolor='black')
356
- ax.add_patch(rect)
357
 
358
- # Draw peptide bond
359
  if i < num_residues - 1:
360
- ax.plot([x_pos+0.3, x_pos+spacing-0.3], [y_pos, y_pos],
361
- color='black', linestyle='-', linewidth=2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
 
363
- # Add residue label with larger font
364
- ax.text(x_pos, y_pos-0.5, residues[i], ha='center', va='top', fontsize=14)
 
365
 
366
- # If cyclic, add arrow connecting ends
367
  if sequence.startswith('cyclo('):
368
- ax.annotate('', xy=(9.5, y_pos), xytext=(0.5, y_pos),
369
- arrowprops=dict(arrowstyle='<->', color='red', lw=2))
370
- ax.text(5, y_pos+0.3, 'Cyclic Connection', ha='center', color='red', fontsize=14)
 
371
 
372
- # Add sequence at the top
373
- ax.text(5, 1.9, f"Sequence: {sequence}", ha='center', va='bottom', fontsize=12)
 
374
 
375
  # Remove axes
376
- ax.set_xticks([])
377
- ax.set_yticks([])
378
- ax.axis('off')
 
379
 
 
380
  return fig
381
 
382
  def process_input(smiles_input=None, file_obj=None, show_linear=False):
@@ -408,7 +489,7 @@ def process_input(smiles_input=None, file_obj=None, show_linear=False):
408
  # Create linear representation if requested
409
  img_linear = None
410
  if show_linear:
411
- fig_linear = create_linear_peptide_viz(sequence)
412
 
413
  # Convert matplotlib figure to image
414
  buf = BytesIO()
 
327
 
328
  return img
329
 
330
+ def create_enhanced_linear_viz(sequence, smiles):
331
  """
332
+ Create an enhanced linear representation showing segment identification process
333
+ with improved segment handling
334
  """
335
+ # Create figure with two subplots
336
+ fig = plt.figure(figsize=(15, 10))
337
+ gs = fig.add_gridspec(2, 1, height_ratios=[1, 2])
338
+ ax_struct = fig.add_subplot(gs[0])
339
+ ax_detail = fig.add_subplot(gs[1])
340
 
341
+ # Parse sequence and get residues
342
  if sequence.startswith('cyclo('):
343
+ residues = sequence[6:-1].split('-')
344
  else:
345
  residues = sequence.split('-')
346
 
347
+ # Get molecule and analyze bonds
348
+ mol = Chem.MolFromSmiles(smiles)
349
+
350
+ # Split SMILES into segments for analysis
351
+ bond_pattern = r'(NC\(=O\)|N\(C\)C\(=O\)|N\dC\(=O\)|OC\(=O\))'
352
+ segments = re.split(bond_pattern, smiles)
353
+ segments = [s for s in segments if s] # Remove empty segments
354
+
355
+ # Debug print
356
+ print(f"Number of residues: {len(residues)}")
357
+ print(f"Number of segments: {len(segments)}")
358
+ print("Segments:", segments)
359
+
360
+ # Top subplot - Basic structure
361
+ ax_struct.set_xlim(0, 10)
362
+ ax_struct.set_ylim(0, 2)
363
+
364
  num_residues = len(residues)
365
+ spacing = 9.0 / (num_residues - 1) if num_residues > 1 else 9.0
366
 
367
+ # Draw basic structure
368
  y_pos = 1.5
369
  for i in range(num_residues):
370
  x_pos = 0.5 + i * spacing
 
372
  # Draw amino acid box
373
  rect = patches.Rectangle((x_pos-0.3, y_pos-0.2), 0.6, 0.4,
374
  facecolor='lightblue', edgecolor='black')
375
+ ax_struct.add_patch(rect)
376
 
377
+ # Draw connecting bonds if not the last residue
378
  if i < num_residues - 1:
379
+ # Find the next bond pattern after this residue
380
+ bond_segment = None
381
+ for j in range(len(segments)):
382
+ if re.match(bond_pattern, segments[j]):
383
+ if j > i*2 and j//2 == i: # Found the right bond
384
+ bond_segment = segments[j]
385
+ break
386
+
387
+ if bond_segment:
388
+ bond_type, is_n_methylated = identify_linkage_type(bond_segment)
389
+ else:
390
+ bond_type = 'peptide' # Default if not found
391
+
392
+ bond_color = 'black' if bond_type == 'peptide' else 'red'
393
+ linestyle = '-' if bond_type == 'peptide' else '--'
394
+
395
+ # Draw bond line
396
+ ax_struct.plot([x_pos+0.3, x_pos+spacing-0.3], [y_pos, y_pos],
397
+ color=bond_color, linestyle=linestyle, linewidth=2)
398
+
399
+ # Add bond type label
400
+ mid_x = x_pos + spacing/2
401
+ bond_label = f"{bond_type}"
402
+ if is_n_methylated:
403
+ bond_label += "\n(N-Me)"
404
+ ax_struct.text(mid_x, y_pos+0.1, bond_label,
405
+ ha='center', va='bottom', fontsize=10,
406
+ color=bond_color)
407
+
408
+ # Add residue label
409
+ ax_struct.text(x_pos, y_pos-0.5, residues[i],
410
+ ha='center', va='top', fontsize=14)
411
+
412
+ # Bottom subplot - Detailed breakdown
413
+ ax_detail.set_ylim(0, len(segments)+1)
414
+ ax_detail.set_xlim(0, 1)
415
+
416
+ # Create detailed breakdown
417
+ segment_y = len(segments) # Start from top
418
+ for i, segment in enumerate(segments):
419
+ y = segment_y - i
420
+
421
+ # Check if this is a bond segment
422
+ if re.match(bond_pattern, segment):
423
+ bond_type, is_n_methylated = identify_linkage_type(segment)
424
+ text = f"Bond {i//2 + 1}: {bond_type}"
425
+ if is_n_methylated:
426
+ text += " (N-methylated)"
427
+ color = 'red'
428
+ else:
429
+ # Get next and previous segments for context
430
+ next_seg = segments[i+1] if i+1 < len(segments) else None
431
+ prev_seg = segments[i-1] if i > 0 else None
432
+
433
+ residue, modifications = identify_residue(segment, next_seg, prev_seg)
434
+ text = f"Residue {i//2 + 1}: {residue}"
435
+ if modifications:
436
+ text += f" ({', '.join(modifications)})"
437
+ color = 'blue'
438
 
439
+ # Add segment analysis
440
+ ax_detail.text(0.05, y, text, fontsize=12, color=color)
441
+ ax_detail.text(0.5, y, f"SMILES: {segment}", fontsize=10, color='gray')
442
 
443
+ # If cyclic, add connection indicator
444
  if sequence.startswith('cyclo('):
445
+ ax_struct.annotate('', xy=(9.5, y_pos), xytext=(0.5, y_pos),
446
+ arrowprops=dict(arrowstyle='<->', color='red', lw=2))
447
+ ax_struct.text(5, y_pos+0.3, 'Cyclic Connection',
448
+ ha='center', color='red', fontsize=14)
449
 
450
+ # Add titles and adjust layout
451
+ ax_struct.set_title("Peptide Structure Overview", pad=20)
452
+ ax_detail.set_title("Segment Analysis Breakdown", pad=20)
453
 
454
  # Remove axes
455
+ for ax in [ax_struct, ax_detail]:
456
+ ax.set_xticks([])
457
+ ax.set_yticks([])
458
+ ax.axis('off')
459
 
460
+ plt.tight_layout()
461
  return fig
462
 
463
  def process_input(smiles_input=None, file_obj=None, show_linear=False):
 
489
  # Create linear representation if requested
490
  img_linear = None
491
  if show_linear:
492
+ fig_linear = create_enhanced_linear_viz(sequence, smiles)
493
 
494
  # Convert matplotlib figure to image
495
  buf = BytesIO()