ModDotPlot 0.9.0__tar.gz → 0.9.1__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.
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.2
2
+ Name: ModDotPlot
3
+ Version: 0.9.1
4
+ Author: Michael Schatz, Adam Phillippy
5
+ Author-email: Alex Sweeten <alex.sweeten@nih.gov>
6
+ Maintainer-email: Alex Sweeten <alex.sweeten@nih.gov>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2024 MarBL
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Keywords: dotplot,sketching,modimizer,heatmap
30
+ Requires-Python: >=3.7
31
+ Description-Content-Type: text/markdown
32
+ License-File: LICENSE
33
+ Requires-Dist: pysam
34
+ Requires-Dist: pandas
35
+ Requires-Dist: plotly
36
+ Requires-Dist: dash
37
+ Requires-Dist: plotnine==0.12.4
38
+ Requires-Dist: palettable
39
+ Requires-Dist: mmh3
40
+ Requires-Dist: tk
41
+ Requires-Dist: setproctitle
42
+ Requires-Dist: numpy
43
+ Requires-Dist: pillow
44
+ Requires-Dist: patchworklib==0.6.3
45
+ Requires-Dist: cairosvg
46
+ Provides-Extra: test
47
+ Requires-Dist: pytest; extra == "test"
48
+ Requires-Dist: pytest-cov; extra == "test"
@@ -19,7 +19,7 @@
19
19
 
20
20
  ## Cite
21
21
 
22
- Alexander P Sweeten, Michael C Schatz, Adam M Phillippy, ModDotPlot—rapid and interactive visualization of tandem repeats, Bioinformatics, Volume 40, Issue 8, August 2024, btae493, https://doi.org/10.1093/bioinformatics/btae493
22
+ Alexander P Sweeten, Michael C Schatz, Adam M Phillippy, ModDotPlot—rapid and interactive visualization of tandem repeats, Bioinformatics, Volume 40, Issue 8, August 2024, btae493, [https://doi.org/10.1093/bioinformatics/btae493](https://pmc.ncbi.nlm.nih.gov/articles/PMC11321072/)
23
23
 
24
24
  If you use ModDotPlot for your research, please cite our software!
25
25
 
@@ -386,10 +386,10 @@ For bug reports or general usage questions, please raise a GitHub issue, or emai
386
386
 
387
387
  ## Known Issues
388
388
 
389
- - Plot width and xlim (limiting the x axis to a different amount) currently do not work. I plan to have those working in v0.9.0.
389
+ -
390
390
 
391
391
  - Mac users might encounter the following unexpected command line output: `/bin/sh: lscpu: command not found`. This is a known issue with Plotnine, the Python plotting library used by ModDotPlot. This can be safely ignored.
392
392
 
393
- - If you encounter an error with the following traceback: `rv = reductor(4) TypeError: cannot pickle 'generator' object`, ths means that you have a newer version of Plotnine that is incompatible with ModDotPlot. Please uninstall plotnine and reinstall version 0.12.4 `pip install plotnine==0.12.4`.
393
+ - If you encounter an error with the following traceback: `rv = reductor(4) TypeError: cannot pickle 'generator' object`, this means that you have a newer version of Plotnine that is incompatible with ModDotPlot. Please uninstall plotnine and reinstall version 0.12.4 `pip install plotnine==0.12.4`.
394
394
 
395
- - In interactive mode, comparing sequences of two sizes will lead to errors in zooming for the larger sequence. I plan to fix this in v0.9.0.
395
+ - There are a number of errors
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ModDotPlot"
7
- version = "0.9.0"
7
+ version = "0.9.1"
8
8
  requires-python = ">= 3.7"
9
9
  dependencies = [
10
10
  "pysam",
@@ -18,7 +18,8 @@ dependencies = [
18
18
  "setproctitle",
19
19
  "numpy",
20
20
  "pillow",
21
- "patchworklib"
21
+ "patchworklib==0.6.3",
22
+ "cairosvg"
22
23
  ]
23
24
  authors = [
24
25
  {name = "Alex Sweeten", email = "alex.sweeten@nih.gov"},
@@ -28,7 +29,8 @@ authors = [
28
29
  maintainers = [
29
30
  {name = "Alex Sweeten", email = "alex.sweeten@nih.gov"}
30
31
  ]
31
- readme = {file = "README.md", content-type = "text/markdown"}
32
+ readme = {file = "README.txt", content-type = "text/markdown"}
33
+ license = {file = "LICENSE"}
32
34
  keywords = ["dotplot", "sketching", "modimizer", "heatmap"]
33
35
 
34
36
  [project.scripts]
@@ -40,12 +42,3 @@ test = [
40
42
  "pytest",
41
43
  "pytest-cov"
42
44
  ]
43
-
44
- [tool.hatch.build.targets.sdist]
45
- exclude = [
46
- "/.github",
47
- "/docs",
48
- ]
49
-
50
- [tool.hatch.build.targets.wheel]
51
- packages = ["src/moddotplot"]
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.2
2
+ Name: ModDotPlot
3
+ Version: 0.9.1
4
+ Author: Michael Schatz, Adam Phillippy
5
+ Author-email: Alex Sweeten <alex.sweeten@nih.gov>
6
+ Maintainer-email: Alex Sweeten <alex.sweeten@nih.gov>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2024 MarBL
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Keywords: dotplot,sketching,modimizer,heatmap
30
+ Requires-Python: >=3.7
31
+ Description-Content-Type: text/markdown
32
+ License-File: LICENSE
33
+ Requires-Dist: pysam
34
+ Requires-Dist: pandas
35
+ Requires-Dist: plotly
36
+ Requires-Dist: dash
37
+ Requires-Dist: plotnine==0.12.4
38
+ Requires-Dist: palettable
39
+ Requires-Dist: mmh3
40
+ Requires-Dist: tk
41
+ Requires-Dist: setproctitle
42
+ Requires-Dist: numpy
43
+ Requires-Dist: pillow
44
+ Requires-Dist: patchworklib==0.6.3
45
+ Requires-Dist: cairosvg
46
+ Provides-Extra: test
47
+ Requires-Dist: pytest; extra == "test"
48
+ Requires-Dist: pytest-cov; extra == "test"
@@ -9,7 +9,8 @@ tk
9
9
  setproctitle
10
10
  numpy
11
11
  pillow
12
- patchworklib
12
+ patchworklib==0.6.3
13
+ cairosvg
13
14
 
14
15
  [test]
15
16
  pytest
@@ -1,4 +1,4 @@
1
- VERSION = "0.9.0"
1
+ VERSION = "0.9.1"
2
2
  COLS = [
3
3
  "#query_name",
4
4
  "query_start",
@@ -179,7 +179,7 @@ def get_parser():
179
179
  "-b",
180
180
  "--bed",
181
181
  default=argparse.SUPPRESS,
182
- help="Path to input bed file(s). Exclusively used in static mode.",
182
+ help="Path to input paired-end bed file(s). Exclusively used in static mode.",
183
183
  nargs="+",
184
184
  )
185
185
 
@@ -273,7 +273,7 @@ def get_parser():
273
273
  )
274
274
 
275
275
  static_parser.add_argument(
276
- "--width", default=9, type=float, nargs="+", help="Plot width."
276
+ "--width", default=18, type=float, help="Plot width (also height for _FULL)."
277
277
  )
278
278
 
279
279
  static_parser.add_argument("--dpi", default=600, type=int, help="Plot dpi.")
@@ -321,8 +321,15 @@ def get_parser():
321
321
  "--axes-ticks",
322
322
  default=None,
323
323
  nargs="+",
324
+ type=int,
324
325
  help="Tick labels to include in x and y axis for custom plots.",
325
326
  )
327
+ # CURRENTLY NOT WORKING
328
+ static_parser.add_argument(
329
+ "--axes-number",
330
+ default=7,
331
+ help="Number of axis ticks labels to include in x and y axis for custom plots, including 0 and seq_length. A minimum of 2 is required, maximum 25.",
332
+ )
326
333
 
327
334
  static_parser.add_argument(
328
335
  "--bin-freq",
@@ -345,10 +352,21 @@ def get_parser():
345
352
  static_parser.add_argument(
346
353
  "--grid-only",
347
354
  action="store_true",
348
- help="Plot comparative plots in an NxN grid like format, skipping individual plots",
355
+ help="Plot comparative plots in an NxN grid like format, skipping individual plots.",
356
+ )
357
+
358
+ static_parser.add_argument(
359
+ "--vector",
360
+ choices=["svg", "pdf", "ps"],
361
+ default="svg",
362
+ help="Output format for vector format.",
349
363
  )
350
364
 
351
- # TODO: Implement static mode logging options
365
+ static_parser.add_argument(
366
+ "--deraster",
367
+ action="store_true",
368
+ help="De-rasterize dotplot in vector format. Note this can lead to large image sizes and make it unusable in image editing software.",
369
+ )
352
370
 
353
371
  return parser
354
372
 
@@ -433,14 +451,13 @@ def main():
433
451
  args.breakpoints = config.get("breakpoints", args.breakpoints)
434
452
  args.bin_freq = config.get("bin_freq", args.bin_freq)
435
453
 
436
- # TODO: Include logging options here
437
- # Check if conflicitng command line args
438
- if args.grid or args.grid_only:
454
+ #
455
+ """if args.grid or args.grid_only:
439
456
  if not (args.compare or args.compare_only) and not args.bed:
440
457
  print(
441
458
  f"Option --grid was selected, but no comparative plots will be produced. Please rerun ModDotPlot with the `--compare` or `--compare-only` option.\n"
442
459
  )
443
- sys.exit(10)
460
+ sys.exit(10)"""
444
461
 
445
462
  # -----------INPUT COMMAND VALIDATION-----------
446
463
  # TODO: More tests!
@@ -465,118 +482,140 @@ def main():
465
482
  double_vals = []
466
483
  single_val_name = []
467
484
  double_val_name = []
468
- try:
469
- for bed in args.bed:
470
- # If args.bed is provided as input, run static mode directly from the bed file. Skip counting input k-mers.
471
- df = read_df_from_file(bed)
472
-
473
- unique_query_names = df["#query_name"].unique()
474
- unique_reference_names = df["reference_name"].unique()
475
- assert len(unique_query_names) == len(unique_reference_names)
476
- # TODO: Change this to allow for multiple seqs in bed file
477
- assert len(unique_reference_names) == 1
478
- self_id_scores = df[df["#query_name"] == df["reference_name"]]
479
- pairwise_id_scores = df[df["#query_name"] != df["reference_name"]]
485
+ xlim_val_grid = 0
486
+ for bed in args.bed:
487
+ # If args.bed is provided as input, run static mode directly from the bed file. Skip counting input k-mers.
488
+ df = read_df_from_file(bed)
489
+
490
+ unique_query_names = df["#query_name"].unique()
491
+ unique_reference_names = df["reference_name"].unique()
492
+ assert len(unique_query_names) == len(unique_reference_names)
493
+ assert len(unique_reference_names) == 1
494
+ self_id_scores = df[df["#query_name"] == df["reference_name"]]
495
+ pairwise_id_scores = df[df["#query_name"] != df["reference_name"]]
496
+ if not args.grid_only:
497
+ print(f"Input bed file {bed} read successfully! Creating plots: \n")
498
+ # Create directory
499
+ if not args.output_dir:
500
+ args.output_dir = os.getcwd()
501
+ if not os.path.exists(args.output_dir):
502
+ os.makedirs(args.output_dir)
503
+ if len(self_id_scores) > 1:
480
504
  if not args.grid_only:
481
- print(
482
- f"Input bed file {bed} read successfully! Creating plots... \n"
505
+ create_plots(
506
+ sdf=None,
507
+ directory=args.output_dir if args.output_dir else ".",
508
+ name_x=unique_query_names[0],
509
+ name_y=unique_query_names[0],
510
+ palette=args.palette,
511
+ palette_orientation=args.palette_orientation,
512
+ no_hist=args.no_hist,
513
+ width=args.width,
514
+ dpi=args.dpi,
515
+ is_freq=args.bin_freq,
516
+ xlim=args.axes_limits,
517
+ custom_colors=args.colors,
518
+ custom_breakpoints=args.breakpoints,
519
+ from_file=df,
520
+ is_pairwise=False,
521
+ axes_labels=args.axes_ticks,
522
+ axes_tick_number=args.axes_number,
523
+ vector_format=args.vector,
524
+ deraster=args.deraster,
483
525
  )
484
- # Create directory
485
- if not args.output_dir:
486
- args.output_dir = os.getcwd()
487
- if not os.path.exists(args.output_dir):
488
- os.makedirs(args.output_dir)
489
- if len(self_id_scores) > 1:
490
- if not args.grid_only:
491
- create_plots(
492
- sdf=None,
493
- directory=args.output_dir if args.output_dir else ".",
494
- name_x=unique_query_names[0],
495
- name_y=unique_query_names[0],
496
- palette=args.palette,
497
- palette_orientation=args.palette_orientation,
498
- no_hist=args.no_hist,
499
- width=args.width,
500
- dpi=args.dpi,
501
- is_freq=args.bin_freq,
502
- xlim=args.axes_limits,
503
- custom_colors=args.colors,
504
- custom_breakpoints=args.breakpoints,
505
- from_file=df,
506
- is_pairwise=False,
507
- axes_labels=args.axes_ticks,
526
+ if args.grid or args.grid_only:
527
+ single_vals.append(df)
528
+ single_val_name.append(unique_query_names[0])
529
+ try:
530
+ max_so_far = max(
531
+ df["query_end"].max(), df["reference_end"].max()
508
532
  )
509
- if args.grid or args.grid_only:
510
- single_vals.append(df)
511
- single_val_name.append(unique_query_names[0])
512
- # Case 2: Pairwise bed file
513
- if len(pairwise_id_scores) > 1:
514
- if not args.grid_only:
515
- create_plots(
516
- sdf=None,
517
- directory=args.output_dir if args.output_dir else ".",
518
- name_x=unique_query_names[0],
519
- name_y=unique_reference_names[0],
520
- palette=args.palette,
521
- palette_orientation=args.palette_orientation,
522
- no_hist=args.no_hist,
523
- width=args.width,
524
- dpi=args.dpi,
525
- is_freq=args.bin_freq,
526
- xlim=args.axes_limits,
527
- custom_colors=args.colors,
528
- custom_breakpoints=args.axes_ticks,
529
- from_file=df,
530
- is_pairwise=True,
531
- axes_labels=args.axes_ticks,
532
- )
533
- if args.grid or args.grid_only:
534
- double_vals.append(df)
535
- double_val_name.append(
536
- [unique_query_names[0], unique_reference_names[0]]
537
- )
538
- # Exit once all bed files have been iterated through
539
- if args.grid or args.grid_only:
540
- print(f"Creating a {len(sequences)}x{len(sequences)} grid.\n")
541
- create_grid(
542
- singles=single_vals,
543
- doubles=double_vals,
544
- directory=args.output_dir if args.output_dir else ".",
545
- palette=args.palette,
546
- palette_orientation=args.palette_orientation,
547
- no_hist=args.no_hist,
548
- single_names=single_val_name,
549
- double_names=double_val_name,
550
- is_freq=args.bin_freq,
551
- xlim=args.axes_limits,
552
- custom_colors=args.colors,
553
- custom_breakpoints=args.axes_ticks,
554
- axes_label=args.axes_ticks,
555
- is_bed=True,
556
- )
557
- sys.exit(0)
558
- except Exception as e:
559
- # Exit code 7: Error getting info from bed file:
560
- # TODO: Change to logs
561
- print(f"Error in bed file: {e}")
562
- sys.exit(7)
533
+ except KeyError:
534
+ max_so_far = max(df["q_en"].max(), df["r_en"].max())
535
+ xlim_val_grid = (
536
+ max_so_far if max_so_far > xlim_val_grid else xlim_val_grid
537
+ )
538
+ # Case 2: Pairwise bed file
539
+ if len(pairwise_id_scores) > 1:
540
+ if not args.grid_only:
541
+ # Potentially sort
542
+ create_plots(
543
+ sdf=None,
544
+ directory=args.output_dir if args.output_dir else ".",
545
+ name_x=unique_query_names[0],
546
+ name_y=unique_reference_names[0],
547
+ palette=args.palette,
548
+ palette_orientation=args.palette_orientation,
549
+ no_hist=args.no_hist,
550
+ width=args.width,
551
+ dpi=args.dpi,
552
+ is_freq=args.bin_freq,
553
+ xlim=args.axes_limits,
554
+ custom_colors=args.colors,
555
+ custom_breakpoints=args.axes_ticks,
556
+ from_file=df,
557
+ is_pairwise=True,
558
+ axes_labels=args.axes_ticks,
559
+ axes_tick_number=args.axes_number,
560
+ vector_format=args.vector,
561
+ deraster=args.deraster,
562
+ )
563
+ if args.grid or args.grid_only:
564
+ double_vals.append(df)
565
+ double_val_name.append(
566
+ [unique_query_names[0], unique_reference_names[0]]
567
+ )
568
+ # Exit once all bed files have been iterated through
569
+ if args.grid or args.grid_only:
570
+ # Determine the number of sequences
571
+ if args.axes_limits:
572
+ xlim_val_grid = args.axes_limits
573
+ print(
574
+ f"Creating a {len(single_val_name)}x{len(single_val_name)} grid.\n"
575
+ )
576
+ create_grid(
577
+ singles=single_vals,
578
+ doubles=double_vals,
579
+ directory=args.output_dir if args.output_dir else ".",
580
+ palette=args.palette,
581
+ palette_orientation=args.palette_orientation,
582
+ single_names=single_val_name,
583
+ double_names=double_val_name,
584
+ is_freq=args.bin_freq,
585
+ xlim=xlim_val_grid,
586
+ custom_colors=args.colors,
587
+ custom_breakpoints=args.axes_ticks,
588
+ axes_label=args.axes_ticks,
589
+ is_bed=True,
590
+ width=args.width,
591
+ breaks=args.axes_ticks,
592
+ deraster=args.deraster,
593
+ vector_format=args.vector,
594
+ )
595
+ sys.exit(0)
563
596
 
564
597
  # -----------INPUT SEQUENCE VALIDATION-----------
565
598
  seq_list = []
599
+ fasta_list = args.fasta.copy()
566
600
  for i in args.fasta:
567
- isValidFasta(i)
568
- headers = getInputHeaders(i)
569
- if len(headers) > 1:
570
- print(f"File {i} contains multiple fasta entries. \n")
571
- counter = 1
572
- for j in headers:
573
- counter += 1
574
- for j in headers:
575
- seq_list.append(j)
601
+ try:
602
+ isValidFasta(i)
603
+ headers = getInputHeaders(i)
604
+
605
+ if len(headers) > 1:
606
+ print(f"File {i} contains multiple fasta entries.\n")
607
+
608
+ seq_list.extend(headers) # Add all headers to seq_list
609
+
610
+ except Exception as e:
611
+ print(
612
+ f"\nUnable to open {i}. Please check it is correctly formatted or compressed...\n"
613
+ )
614
+ fasta_list.remove(i)
576
615
 
577
616
  # -----------LOAD SEQUENCES INTO MEMORY-----------
578
617
  kmer_list = []
579
- for i in args.fasta:
618
+ for i in fasta_list:
580
619
  kmer_list.append(readKmersFromFile(i, args.kmer, False))
581
620
  k_list = [item for sublist in kmer_list for item in sublist]
582
621
  # Throw error if compare only selected with one sequence.
@@ -901,18 +940,6 @@ def main():
901
940
  else:
902
941
  seq_sparsity = 2 ** (int(math.log2(seq_sparsity - 1)) + 1)
903
942
  expectation = round(win / seq_sparsity)
904
- xaxis = 0
905
- width = 0
906
- """if isinstance(args.xaxis, int) or args.xaxis == None:
907
- xaxis = args.xaxis
908
- else:
909
- assert len(args.xaxis) == len(sequences)
910
- xaxis = args.xaxis[i]"""
911
- if isinstance(args.width, int):
912
- width = args.width
913
- else:
914
- assert len(args.width) == len(sequences)
915
- width = args.width[i]
916
943
 
917
944
  print(f"Computing self identity matrix for {sequences[i][0]}... \n")
918
945
  # TODO: Logging here
@@ -952,7 +979,7 @@ def main():
952
979
  bedfile.write("\t".join(map(str, row)) + "\n")
953
980
  print(f"Saved bed file to {bedfile_output}\n")
954
981
 
955
- if not args.no_plot:
982
+ if (not args.no_plot) and (not args.grid_only):
956
983
  create_plots(
957
984
  sdf=[bed],
958
985
  directory=args.output_dir if args.output_dir else ".",
@@ -961,7 +988,7 @@ def main():
961
988
  palette=args.palette,
962
989
  palette_orientation=args.palette_orientation,
963
990
  no_hist=args.no_hist,
964
- width=width,
991
+ width=args.width,
965
992
  dpi=args.dpi,
966
993
  is_freq=args.bin_freq,
967
994
  xlim=args.axes_limits,
@@ -970,16 +997,22 @@ def main():
970
997
  from_file=None,
971
998
  is_pairwise=False,
972
999
  axes_labels=args.axes_ticks,
1000
+ axes_tick_number=args.axes_number,
1001
+ vector_format=args.vector,
1002
+ deraster=args.deraster,
973
1003
  )
974
1004
 
975
1005
  # -----------COMPUTE COMPARATIVE PLOTS-----------
976
1006
  # TODO: Optimize computations so that largest sequence doesn't need to be redone all the time
977
- if (args.compare or args.compare_only) and len(sequences) > 1:
1007
+ if (args.compare or args.compare_only or args.grid or args.grid_only) and len(
1008
+ sequences
1009
+ ) > 1:
978
1010
  # Set window size to args.window. Otherwise, set it to n/resolution
979
1011
 
980
1012
  if args.grid or args.grid_only:
981
1013
  grid_val_doubles = []
982
1014
  grid_val_double_names = []
1015
+ xlim_val_grid = 0
983
1016
 
984
1017
  for i in range(len(sequences)):
985
1018
  for j in range(i + 1, len(sequences)):
@@ -1060,7 +1093,7 @@ def main():
1060
1093
  grid_val_double_names.append(
1061
1094
  [larger_seq_name, smaller_seq_name]
1062
1095
  )
1063
-
1096
+ xlim_val_grid = max(larger_length, xlim_val_grid)
1064
1097
  if not args.no_bed:
1065
1098
  # Log saving bed file
1066
1099
  if not args.output_dir:
@@ -1083,7 +1116,7 @@ def main():
1083
1116
  bedfile.write("\t".join(map(str, row)) + "\n")
1084
1117
  print(f"Saved bed file to {bedfile_output}\n")
1085
1118
 
1086
- if not args.no_plot:
1119
+ if (not args.no_plot) and (not args.grid_only):
1087
1120
  create_plots(
1088
1121
  sdf=[bed],
1089
1122
  directory=args.output_dir if args.output_dir else ".",
@@ -1092,7 +1125,7 @@ def main():
1092
1125
  palette=args.palette,
1093
1126
  palette_orientation=args.palette_orientation,
1094
1127
  no_hist=args.no_hist,
1095
- width=None,
1128
+ width=args.width,
1096
1129
  dpi=args.dpi,
1097
1130
  is_freq=args.bin_freq,
1098
1131
  xlim=args.axes_limits,
@@ -1101,6 +1134,9 @@ def main():
1101
1134
  from_file=None,
1102
1135
  is_pairwise=True,
1103
1136
  axes_labels=args.axes_ticks,
1137
+ axes_tick_number=args.axes_number,
1138
+ vector_format=args.vector,
1139
+ deraster=args.deraster,
1104
1140
  )
1105
1141
 
1106
1142
  if args.grid or args.grid_only:
@@ -1111,15 +1147,18 @@ def main():
1111
1147
  directory=args.output_dir if args.output_dir else ".",
1112
1148
  palette=args.palette,
1113
1149
  palette_orientation=args.palette_orientation,
1114
- no_hist=args.no_hist,
1115
1150
  single_names=grid_val_single_names,
1116
1151
  double_names=grid_val_double_names,
1117
1152
  is_freq=args.bin_freq,
1118
- xlim=args.axes_limits,
1153
+ xlim=xlim_val_grid,
1119
1154
  custom_colors=args.colors,
1120
1155
  custom_breakpoints=args.axes_ticks,
1121
1156
  axes_label=args.axes_ticks,
1122
1157
  is_bed=False,
1158
+ width=args.width,
1159
+ breaks=args.axes_ticks,
1160
+ deraster=args.deraster,
1161
+ vector_format=args.vector,
1123
1162
  )
1124
1163
 
1125
1164
 
@@ -7,6 +7,7 @@ import os
7
7
  import pickle
8
8
  import re
9
9
  import numpy as np
10
+ import gzip
10
11
 
11
12
  tab_b = bytes.maketrans(b"ACTG", b"TGAC")
12
13
 
@@ -43,7 +44,8 @@ def generateKmersFromFasta(seq: Sequence[str], k: int, quiet: bool) -> Iterable[
43
44
 
44
45
  def isValidFasta(file_path):
45
46
  try:
46
- with open(file_path, "r") as file:
47
+ open_func = gzip.open if file_path.endswith(".gz") else open
48
+ with open_func(file_path, "rt") as file:
47
49
  in_sequence = False
48
50
  for line in file:
49
51
  line = line.strip()
@@ -144,7 +146,10 @@ def readKmersFromFile(filename: str, ksize: int, quiet: bool) -> List[List[int]]
144
146
 
145
147
  def getInputHeaders(filename: str) -> List[str]:
146
148
  header_list = []
147
- seq = pysam.FastaFile(filename)
149
+ try:
150
+ seq = pysam.FastaFile(filename)
151
+ except OSError:
152
+ seq = None
148
153
  for seq_id in seq.references:
149
154
  header_list.append(seq_id)
150
155