11# ## =========================================================================
2- # ## combine_germline_dbs()
2+ # ## combine_germline_dbs() & combine_c_region_dbs()
33# ## -------------------------------------------------------------------------
44# ##
55
66
7+ .check_comb_db_name <- function (db_name )
8+ {
9+ if (! isSingleNonWhiteString(db_name ))
10+ stop(wmsg(" 'db_name' must be a single (non-empty) string" ))
11+ if (has_whitespace(db_name ))
12+ stop(wmsg(" 'db_name' cannot contain whitespace characters" ))
13+ if (! has_prefix(db_name , " comb" ))
14+ stop(wmsg(" 'db_name' must start with \" comb\" " ))
15+ }
16+
17+ .check_suffixes <- function (suffix1 , suffix2 )
18+ {
19+ if (! isSingleString(suffix1 ))
20+ stop(wmsg(" 'suffix1' must be a single string" ))
21+ if (has_whitespace(suffix1 ))
22+ stop(wmsg(" 'suffix1' cannot contain whitespace characters" ))
23+ if (! isSingleString(suffix2 ))
24+ stop(wmsg(" 'suffix2' must be a single string" ))
25+ if (has_whitespace(suffix2 ))
26+ stop(wmsg(" 'suffix2' cannot contain whitespace characters" ))
27+ if (suffix1 == suffix2 )
28+ stop(wmsg(" 'suffix1' and 'suffix2' must be different" ))
29+ }
30+
31+ .stop_on_colliding_allele_names <- function ()
32+ {
33+ msg1 <- " Allele name collisions!"
34+ msg2 <- c(" Even after adding 'suffix1' to the allele names of the first " ,
35+ " db, and 'suffix2' to the allele names of the second db, some " ,
36+ " allele names are still colliding. This can be avoided by using " ,
37+ " more specific suffixes." )
38+ stop(wmsg(msg1 ), " \n " , wmsg(msg2 ))
39+ }
40+
741.combine_locus_alleles <- function (locus , alleles1 , alleles2 , suffix1 , suffix2 )
842{
943 stopifnot(isSingleNonWhiteString(locus ),
1044 is(alleles1 , " DNAStringSet" ), is(alleles2 , " DNAStringSet" ),
11- isSingleNonWhiteString (suffix1 ), isSingleNonWhiteString (suffix2 ))
45+ isSingleString (suffix1 ), isSingleString (suffix2 ))
1246 locus_alleles1 <- alleles1 [substr(names(alleles1 ), 1L , 3L ) == locus ]
1347 locus_alleles2 <- alleles2 [substr(names(alleles2 ), 1L , 3L ) == locus ]
1448 # # Add user-supplied suffixes to disambiguate allele names.
1549 names(locus_alleles1 ) <- add_suffix(names(locus_alleles1 ), suffix1 )
1650 names(locus_alleles2 ) <- add_suffix(names(locus_alleles2 ), suffix2 )
17- c(locus_alleles1 , locus_alleles2 )
51+ locus_alleles <- c(locus_alleles1 , locus_alleles2 )
52+ if (anyDuplicated(names(locus_alleles )))
53+ .stop_on_colliding_allele_names()
54+ locus_alleles
1855}
1956
20- .combine_region_dbs <- function (destdir , db_name1 , db_name2 , suffix1 , suffix2 ,
57+ # ## We only support combining region dbs for the IG loci at the moment.
58+ .combine_region_dbs <- function (destdir , db_path1 , db_path2 , suffix1 , suffix2 ,
2159 region_type , verbose = FALSE )
2260{
23- alleles1 <- load_germline_db( db_name1 , region_types = region_type )
24- alleles2 <- load_germline_db( db_name2 , region_types = region_type )
61+ alleles1 <- readDNAStringSet(get_db_fasta_file( db_path1 , region_type ) )
62+ alleles2 <- readDNAStringSet(get_db_fasta_file( db_path2 , region_type ) )
2563 loci1 <- substr(names(alleles1 ), 1 , 3 )
2664 loci2 <- substr(names(alleles2 ), 1 , 3 )
2765 stopifnot(all(loci1 %in% IG_LOCI ), all(loci2 %in% IG_LOCI ))
3371
3472 locus2alleles <- locus2alleles [lengths(locus2alleles ) != 0L ]
3573 stopifnot(length(locus2alleles ) != 0L )
36- names(locus2alleles ) <- paste0(names(locus2alleles ), region_type , " .fasta" )
3774
38- fasta_files <- vapply(locus2alleles ,
39- function (alleles ) {
75+ loci <- names(locus2alleles )
76+ fasta_files <- vapply(loci ,
77+ function (locus ) {
78+ alleles <- locus2alleles [[locus ]]
4079 fasta_file <- tempfile(fileext = " .fasta" )
4180 writeXStringSet(alleles , fasta_file )
81+ if (verbose ) {
82+ msg <- c(" Combined and saved " , length(alleles ), " " ,
83+ region_type , " alleles for locus " , locus , " to " ,
84+ " temp file " , basename(fasta_file ))
85+ message(wmsg(msg ))
86+ }
4287 fasta_file
4388 },
4489 character (1 ))
90+ if (verbose )
91+ message(" " )
92+ on.exit(unlink(fasta_files ))
4593
94+ names(fasta_files ) <- paste0(loci , region_type , " .fasta" )
4695 create_region_db(fasta_files , destdir , region_type = region_type ,
4796 verbose = verbose )
48- lapply(fasta_files , nuke_file )
4997}
5098
99+
100+ # ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
101+ # ## combine_germline_dbs()
102+ # ##
103+
51104.combine_db_intdata <- function (destdir , db_name1 , db_name2 , suffix1 , suffix2 ,
52105 verbose = FALSE )
53106{
81134}
82135
83136.do_combine_germline_dbs <- function (destdir ,
84- db_name1 , db_name2 , suffix1 , suffix2 ,
137+ db_path1 , db_path2 , suffix1 , suffix2 ,
85138 verbose = FALSE )
86139{
87- if (! isSingleNonWhiteString(db_name1 ))
88- stop(wmsg(" 'db_name1' must be a single (non-empty) string" ))
89- if (! isSingleNonWhiteString(db_name2 ))
90- stop(wmsg(" 'db_name2' must be a single (non-empty) string" ))
91- if (! isSingleString(suffix1 ))
92- stop(wmsg(" 'suffix1' must be a single string" ))
93- if (has_whitespace(suffix1 ))
94- stop(wmsg(" 'suffix1' cannot contain whitespace characters" ))
95- if (! isSingleString(suffix2 ))
96- stop(wmsg(" 'suffix2' must be a single string" ))
97- if (has_whitespace(suffix2 ))
98- stop(wmsg(" 'suffix2' cannot contain whitespace characters" ))
99140 for (region_type in VDJ_REGION_TYPES )
100- .combine_region_dbs(destdir , db_name1 , db_name2 , suffix1 , suffix2 ,
141+ .combine_region_dbs(destdir , db_path1 , db_path2 , suffix1 , suffix2 ,
101142 region_type , verbose = verbose )
143+ db_name1 <- basename(db_path1 )
144+ db_name2 <- basename(db_path2 )
102145 .combine_db_intdata(destdir , db_name1 , db_name2 , suffix1 , suffix2 ,
103146 verbose = verbose )
104147 .combine_db_auxdata(destdir , db_name1 , db_name2 , suffix1 , suffix2 ,
105148 verbose = verbose )
106149}
107150
108-
109- # ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
110- # ## combine_germline_dbs()
111- # ##
112-
113- # ## Combine two existing germline dbs, typically from two different
114- # ## organisms, into one hybrid germline db.
151+ # ## Combine two existing germline dbs, typically (but not necessarily) from
152+ # ## two different organisms, into one hybrid germline db.
115153# ## Note that allele names are usually not unique across species.
116154# ## Arguments 'suffix1' and 'suffix2' can be used to disambiguate them.
117155combine_germline_dbs <- function (db_name ,
118156 db_name1 , db_name2 , suffix1 , suffix2 ,
119157 overwrite = FALSE , verbose = FALSE )
120158{
121- if (! isSingleNonWhiteString(db_name ))
122- stop(wmsg(" 'db_name' must be a single (non-empty) string" ))
123- if (has_whitespace(db_name ))
124- stop(wmsg(" 'db_name' cannot contain whitespace characters" ))
125- if (! has_prefix(db_name , " comb" ))
126- stop(wmsg(" 'db_name' must start with \" comb\" " ))
159+ .check_comb_db_name(db_name )
160+ check_germline_db_name(db_name1 , what = " 'db_name1'" )
161+ check_germline_db_name(db_name2 , what = " 'db_name2'" )
162+ .check_suffixes(suffix1 , suffix2 )
127163
128164 if (! isTRUEorFALSE(overwrite ))
129165 stop(wmsg(" 'overwrite' must be TRUE or FALSE" ))
@@ -132,7 +168,10 @@ combine_germline_dbs <- function(db_name,
132168
133169 db_path <- get_germline_db_path(db_name )
134170 if (dir.exists(db_path ) && ! overwrite )
135- stop_on_existing_cached_germline_db(db_name )
171+ stop_on_existing_germline_db(db_name )
172+
173+ db_path1 <- get_germline_db_path(db_name1 )
174+ db_path2 <- get_germline_db_path(db_name2 )
136175
137176 # # We first create the combined germline db in a temporary folder, and,
138177 # # only if successful, we replace 'db_path' with the temporary folder.
@@ -142,10 +181,55 @@ combine_germline_dbs <- function(db_name,
142181 tmp_destdir <- tempfile(" germline_db_" )
143182 dir.create(tmp_destdir )
144183 on.exit(nuke_file(tmp_destdir ))
145- .do_combine_germline_dbs(tmp_destdir , db_name1 , db_name2 , suffix1 , suffix2 ,
184+ .do_combine_germline_dbs(tmp_destdir , db_path1 , db_path2 , suffix1 , suffix2 ,
146185 verbose = verbose )
147186 rename_file(tmp_destdir , db_path , replace = TRUE )
148187
149188 invisible (db_name )
150189}
151190
191+
192+ # ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
193+ # ## combine_c_region_dbs()
194+ # ##
195+
196+ # ## Combine two existing C-region dbs, typically (but not necessarily) from
197+ # ## two different organisms, into one hybrid C-region db.
198+ # ## Note that allele names are usually not unique across species.
199+ # ## Arguments 'suffix1' and 'suffix2' can be used to disambiguate them.
200+ combine_c_region_dbs <- function (db_name ,
201+ db_name1 , db_name2 , suffix1 , suffix2 ,
202+ overwrite = FALSE , verbose = FALSE )
203+ {
204+ .check_comb_db_name(db_name )
205+ check_c_region_db_name(db_name1 , what = " 'db_name1'" )
206+ check_c_region_db_name(db_name2 , what = " 'db_name2'" )
207+ .check_suffixes(suffix1 , suffix2 )
208+
209+ if (! isTRUEorFALSE(overwrite ))
210+ stop(wmsg(" 'overwrite' must be TRUE or FALSE" ))
211+ if (! isTRUEorFALSE(verbose ))
212+ stop(wmsg(" 'verbose' must be TRUE or FALSE" ))
213+
214+ db_path <- get_c_region_db_path(db_name )
215+ if (dir.exists(db_path ) && ! overwrite )
216+ stop_on_existing_c_region_db(db_name )
217+
218+ db_path1 <- get_c_region_db_path(db_name1 )
219+ db_path2 <- get_c_region_db_path(db_name2 )
220+
221+ # # We first create the combined C-region db in a temporary folder, and,
222+ # # only if successful, we replace 'db_path' with the temporary folder.
223+ # # Otherwise we destroy the temporary folder and raise an error. This
224+ # # achieves atomicity and avoids loosing the content of the existing
225+ # # 'db_path' in case something goes wrong.
226+ tmp_destdir <- tempfile(" c_region_db_" )
227+ dir.create(tmp_destdir )
228+ on.exit(nuke_file(tmp_destdir ))
229+ .combine_region_dbs(tmp_destdir , db_path1 , db_path2 , suffix1 , suffix2 ,
230+ " C" , verbose = verbose )
231+ rename_file(tmp_destdir , db_path , replace = TRUE )
232+
233+ invisible (db_name )
234+ }
235+
0 commit comments