-
Notifications
You must be signed in to change notification settings - Fork 371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Partial fix of coordinate casting to short in MarkDuplicates #1442
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,10 @@ | |
import picard.util.GraphUtils; | ||
|
||
import java.io.Serializable; | ||
import java.util.*; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* Contains methods for finding optical/co-localized/sequencing duplicates. | ||
|
@@ -327,16 +330,19 @@ private PhysicalLocation keeperOrNull(final List<? extends PhysicalLocation> lis | |
/** Simple method to test whether two physical locations are close enough to each other to be deemed optical dupes. */ | ||
private boolean closeEnough(final PhysicalLocation lhs, final PhysicalLocation rhs, final int distance) { | ||
return lhs != rhs && // no comparing an object to itself (checked using object identity)! | ||
lhs.hasLocation() && rhs.hasLocation() && // no comparing objects without locations | ||
lhs.getReadGroup() == rhs.getReadGroup() && // must be in the same RG to be optical duplicates | ||
lhs.getTile() == rhs.getTile() && // and the same tile | ||
Math.abs(lhs.getX() - rhs.getX()) <= distance && | ||
Math.abs(lhs.getY() - rhs.getY()) <= distance; | ||
lhs.hasLocation() && rhs.hasLocation() && // no comparing objects without locations | ||
lhs.getReadGroup() == rhs.getReadGroup() && // must be in the same RG to be optical duplicates | ||
lhs.getTile() == rhs.getTile() && // and the same tile | ||
closeEnoughShort(lhs, rhs, distance); | ||
} | ||
|
||
private boolean closeEnoughShort(final PhysicalLocation lhs, final PhysicalLocation rhs, final int distance) { | ||
return lhs != rhs && | ||
Math.abs(lhs.getX() - rhs.getX()) <= distance && | ||
Math.abs(lhs.getY() - rhs.getY()) <= distance; | ||
// Since the X and Y coordinates are constrained to short values, they can also become negative when | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm... this method should have been named something less overloaded like "closeEnoughQuick" to make it clearer that this checks fewer things and not short casted things given that the underlying values could be ints or shorts... Now that you have made this change you perhaps is a correct description as now this method will always check adjacency in short space even if the underlying physical location still has integers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had to do some arithmetic to convince myself that this works. Assuming your goal is to make it so that both 32768 and 32767 adjacent without disturbing the 65536 and 65535 adjacency I think this succeeded. However I do not think it is necessary to perform the operation forwards and backwards, the absolute value operation (even accounting for overflowing from the shorts) will not be changed by flipping the order by virtue of the fact that this calculation is being performed in integer space whereas the underlying data overflowed in short space. Unless your scaling factor is in the region of |
||
// cast from int to short. This code compares them while taking that into account. | ||
(Math.abs((lhs.getX() - rhs.getX()) % Short.MAX_VALUE) <= distance || | ||
Math.abs((rhs.getX() - lhs.getX()) % Short.MAX_VALUE) <= distance) && | ||
(Math.abs((lhs.getY() - rhs.getY()) % Short.MAX_VALUE) <= distance || | ||
Math.abs((rhs.getY() - lhs.getY()) % Short.MAX_VALUE) <= distance); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
@HD VN:1.6 SO:coordinate | ||
@SQ SN:1 LN:200000000 | ||
@SQ SN:2 LN:200000000 | ||
@RG ID:00001_1#1 LB:22222222 PL:ILLUMINA SM:AW99 | ||
@PG ID:MarkDuplicates VN:2.21.4-2-ga3021a7-SNAPSHOT CL:MarkDuplicates TAG_DUPLICATE_SET_MEMBERS=true TAGGING_POLICY=All INPUT=[short_test.sam] OUTPUT=short_test_out.sam METRICS_FILE=short_test_stat.txt OPTICAL_DUPLICATE_PIXEL_DISTANCE=2500 MAX_SEQUENCES_FOR_DISK_READ_ENDS_MAP=50000 MAX_FILE_HANDLES_FOR_READ_ENDS_MAP=8000 SORTING_COLLECTION_SIZE_RATIO=0.25 REMOVE_SEQUENCING_DUPLICATES=false CLEAR_DT=true DUPLEX_UMI=false ADD_PG_TAG_TO_READS=true REMOVE_DUPLICATES=false ASSUME_SORTED=false DUPLICATE_SCORING_STRATEGY=SUM_OF_BASE_QUALITIES PROGRAM_RECORD_ID=MarkDuplicates PROGRAM_GROUP_NAME=MarkDuplicates READ_NAME_REGEX=<optimized capture of last three ':' separated fields as numeric values> MAX_OPTICAL_DUPLICATE_SET_SIZE=300000 VERBOSITY=INFO QUIET=false VALIDATION_STRINGENCY=STRICT COMPRESSION_LEVEL=5 MAX_RECORDS_IN_RAM=500000 CREATE_INDEX=false CREATE_MD5_FILE=false GA4GH_CLIENT_SECRETS=client_secrets.json USE_JDK_DEFLATER=false USE_JDK_INFLATER=false PN:MarkDuplicates | ||
AW7_00001:1:2101:29376:32760 99 1 2239203 60 151M = 2239280 228 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT AAFFFJJJJJJJJJJJJJJJJJJJJFJJJJJJFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJAFJJFJF MC:Z:151M PG:Z:MarkDuplicates RG:Z:00001_1#1 DI:i:0 DS:i:2 | ||
AW7_00001:1:2101:29346:33023 1123 1 2239203 60 151M = 2239280 228 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT AAFFFJJJJJJJJJJJJJJJJJJJAJFJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJAJJJJJF MC:Z:151M PG:Z:MarkDuplicates RG:Z:00001_1#1 DI:i:0 DS:i:2 DT:Z:LB | ||
AW7_00001:1:2101:29346:98296 1123 1 2239203 60 151M = 2239280 228 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT AAFFFJJJJJJJJJJJJJJJJJJJAJFJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJAJJJJJF MC:Z:151M PG:Z:MarkDuplicates RG:Z:00001_1#1 DI:i:0 DS:i:2 DT:Z:LB | ||
AW7_00001:1:2101:29376:32760 147 1 2239280 60 151M = 2239203 -228 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT JJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFFAA MC:Z:151M PG:Z:MarkDuplicates RG:Z:00001_1#1 DI:i:0 DS:i:2 | ||
AW7_00001:1:2101:29346:33023 1171 1 2239280 60 151M = 2239203 -228 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT JJJJJFJJJJJJJJJJJJJJJJJJJJJFJJF7JJJFJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJFFAAA MC:Z:151M PG:Z:MarkDuplicates RG:Z:00001_1#1 DI:i:0 DS:i:2 DT:Z:LB | ||
AW7_00001:1:2101:29346:98296 1171 1 2239280 60 151M = 2239203 -228 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT JJJJJFJJJJJJJJJJJJJJJJJJJJJFJJF7JJJFJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJFFAAA MC:Z:151M PG:Z:MarkDuplicates RG:Z:00001_1#1 DI:i:0 DS:i:2 DT:Z:LB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the typical use case this might actually make a difference since we are compressing the pixel distance by 2500/100 or 25 and then int scaling, which will end up introducing approximately a 1% truncation in every case. That is probably fine given how unlikely it is to substantially change the optical duplicate finding. I do not however think this should not be defined by
OpticalDuplicateFinder.DEFAULT_OPTICAL_DUPLICATE_DISTANCE
and we should fix some other variable instead since the error range shouldn't really have anything to do with the default pixel distance.It would also seem prudent to ensure that we don't ever set a value below 1 here (i.e. we don't ever want to "inflate" the pixel coordinates if the user selects a pixel distance < 100).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to think of a scaling factor that keeps the default behaviour the same....I guess I could add an additional argument, but I thought this admitted hack is good enough....if there are other ideas, I'm happy to consider.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems reasonable. I do think it seems bizzare that if we were to change the default to say 2500 (which I think is the standard for most of our pipelines) that we would be compressing by a factor of 25 less than we were before which could cause confusion of unintended consequences. I think we should make a separate variable that pegs the to 100 to make it a little clearer why we are doing it this way. I still think we should avoid ever scaling by fractional value however.
final double scale = Math.max(OPTICAL_DUPLICATE_PIXEL_DISTANCE/(double) OpticalDuplicateFinder.OPTICAL_DUPLICATE_PIXEL_SCALING_FACTOR, 1.0);