You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
from our previous thread (#330 in kipoi/kipoi) re: DeepBind dataloaders, I would +1 pyfaidx for dealing with fasta indexing. It has fewer dependencies than GenomeLake (sp?).
the actual encoding from concise was good, but maybe could be factored out of the package? Installing the whole concise package just to encode DNA was a bit overkill
Reacted by Žiga Avsec and Maria Katherine Mejia Guerra
Agree. We should also add proper handling of variable widths etc.
I will indeed factor out the one-hot-encoder from concise for the beginning to make things simple. It will not be as fast as genomelake which uses cython to compile the one-hot-encode function.
Do you think one should install all the dependencies for all the dataloaders in the dataloaders package or should these be installed on the fly?
@Avsecz my issue was that genomelake - pysam could not handle a fasta file that contained a collection of intervals with the corresponding subsequences. It expected an entire chromosome, and each subsequence where the subsequences could be extracted from it.
I will indeed factor out the one-hot-encoder from concise for the beginning to make things simple. It will not be as fast as genomelake which uses cython to compile the one-hot-encode function.
Did you do profiling of cythonized versus pure python one-hot encoding? How much of a speedup did it provide?
Do you think one should install all the dependencies for all the dataloaders in the dataloaders package or should these be installed on the fly?
I'm not sure. I think for users, it would be better to have dependencies installed on an as-needed basis. However, this might be more work for you, so I understand if you'd want to bundle all dependencies together whe then install a kipoi/dataloaders package (via conda I imagine?)
Did you do profiling of cythonized versus pure python one-hot encoding? How much of a speedup did it provide?
Yup. I did the benchmarks. For 1kb it's 300us vs 50us and for 10kb is 3ms vs 0.5 ms. Hence 6x speedup. I really want to make these dataloaders as fast as possible so that they become the default to people training models as well.
@Avsecz my issue was that genomelake - pysam could not handle a fasta file that contained a collection of intervals with the corresponding subsequences. It expected an entire chromosome, and each subsequence where the subsequences could be extracted from it.
I migrated genomelake to pyfaidx. Need to fix the unit tests and then it should work. Could you please send me a slashed down version of your fasta file (containing a single sequence of length ~100) and the expected result so that I can add it to the unit-tests. Migrating to pyfaidx will also solve the installation issues - if conda channels were in the wrong order, then (old) pysam from anaconda was chosen.
I'm not sure. I think for users, it would be better to have dependencies installed on an as-needed basis. However, this might be more work for you, so I understand if you'd want to bundle all dependencies together whe then install a kipoi/dataloaders package (via conda I imagine?)
Ok. I think that's a good idea especially if the set of data-loaders and their dependencies starts growing. It's actually not more work. We anyway need to annotate each dataloader as in dataloader.yaml.
thanks for the discussion - I am currently implementing a first draft of the dataloaders repo and I think my suggestion agrees with many of your points. I have opted to:
write my own FastaExtractor class and called it FastaReader to avoid confusion. This is necessary as some models (e.g: lsgkm-SVM) need string inputs, others one-hot encoded input, etc. It is therefore a wrapper around pyfaidx so that it operates with pybedtools.Interval objects.
the string sequence output can be converted by transformer methods, one of which is the onehot_trafo, another will be char_list_trafo:
onehot_trafo is at the moment a three-liner which can at any point be replaced with the onehot method in genomelake. I didn't do that to avoid genomelake dependency only because of this function
char_list_trafo converts the sequence string returned by FastaReader into list of characters, as required by some models.
For one-hot encoded sequences I define a Reshaper class that can add "dummy" dimensions and swap the order of the sequence and alphabet axes as required by the model.
@lzamparo btw. I am more than happy to use a fasta reading package that has the functionality you requested. pyfaidx does not have the functionality that you have requested - e.g.: requesting the sequence from genomic interval chr15:98503515-98503517 given the fasta example file in your gist in kipoi/kipoi#330. pyfaidx inteprets the entire string after the ">" as a sequence/chromosome name. If you can point me to the fasta reader that you have in mind which is capable to handle this the way you specified and if the that fasta reader complies with the fasta standards then I am more than happy to replace pyfaidx with that one.
@krrome I've not used get_seq before, but I used the dict interface of Pyfaidx.Fasta to do slicing on Fasta records from a file organized like the one in my original gist you reference.
There is one snag, which is you need to convert to relative indexing of the bases from the absolute indexing of the interval, but that's pretty fast. Have a look at the TruncSeqDataset dataloader I made, you can see how I'm taking subsequences in __getitem__
@lzamparo thanks for the link. I could add your way of querying in case the default get_seq throws a FetchError.. but the problem I can see there is that it will only work if the bed query is matched by a fasta file entry...
in any case if your suggestion solves your problem we can add it to the default dataloader, if @Avsecz agrees.
.. but the problem I can see there is that it will only work if the bed query is matched by a fasta file entry...
True, I ensured there would be correspondance by construction. Though I think it can handle the .other common use case, where you have one fasta file per chromosome, and the intervals can be taken as a subset without any conversion to relative sequences. Up to you to decide how to handle the case where an interval has no match in the fasta provided.
Great! Thanks @lzamparo . I'll have a closer look at your implementation tomorrow and add the provided files to unit-tests.
Update
I'm almost done writing the transforms module that contains all the useful pre-processing functions like one-hot encoding, tokenizing or sequence trimming. I re-factored one-hot-encoding functions from concise and also imported the fast one-hot-encoding from genomelake (for the DNA case)
@Avsecz +1 for both transforms you suggest below, I can think of some handy use-cases for both. Also useful might be a random substring transform? I can imagine a scenario when you are working with longer sequences, but the property you're trying to predict is valid over the length of the sequence, and you want to use this for data augmentation.
I've started a new issue to keep track of the additional dataloaders: #8. The package is ready and on pypi pip install kipoiseq. I also created a small colab notebook: link.
Activity
lzamparo commentedon Oct 1, 2018
Two suggestions:
Avsecz commentedon Oct 1, 2018
Agree. We should also add proper handling of variable widths etc.
I will indeed factor out the one-hot-encoder from concise for the beginning to make things simple. It will not be as fast as genomelake which uses cython to compile the one-hot-encode function.
Do you think one should install all the dependencies for all the dataloaders in the dataloaders package or should these be installed on the fly?
Avsecz commentedon Oct 1, 2018
@lzamparo what was your issue once again with genomelake - pysam?
Avsecz commentedon Oct 1, 2018
Migrating from pysam to pyfaidx: kundajelab/genomelake#19
lzamparo commentedon Oct 2, 2018
@Avsecz my issue was that genomelake - pysam could not handle a fasta file that contained a collection of intervals with the corresponding subsequences. It expected an entire chromosome, and each subsequence where the subsequences could be extracted from it.
lzamparo commentedon Oct 2, 2018
Did you do profiling of cythonized versus pure python one-hot encoding? How much of a speedup did it provide?
I'm not sure. I think for users, it would be better to have dependencies installed on an as-needed basis. However, this might be more work for you, so I understand if you'd want to bundle all dependencies together whe then install a kipoi/dataloaders package (via conda I imagine?)
Avsecz commentedon Oct 2, 2018
Yup. I did the benchmarks. For 1kb it's 300us vs 50us and for 10kb is 3ms vs 0.5 ms. Hence 6x speedup. I really want to make these dataloaders as fast as possible so that they become the default to people training models as well.
I migrated genomelake to pyfaidx. Need to fix the unit tests and then it should work. Could you please send me a slashed down version of your fasta file (containing a single sequence of length ~100) and the expected result so that I can add it to the unit-tests. Migrating to pyfaidx will also solve the installation issues - if conda channels were in the wrong order, then (old) pysam from anaconda was chosen.
Ok. I think that's a good idea especially if the set of data-loaders and their dependencies starts growing. It's actually not more work. We anyway need to annotate each dataloader as in
dataloader.yaml.krrome commentedon Oct 2, 2018
thanks for the discussion - I am currently implementing a first draft of the dataloaders repo and I think my suggestion agrees with many of your points. I have opted to:
FastaExtractorclass and called itFastaReaderto avoid confusion. This is necessary as some models (e.g: lsgkm-SVM) need string inputs, others one-hot encoded input, etc. It is therefore a wrapper around pyfaidx so that it operates withpybedtools.Intervalobjects.transformermethods, one of which is theonehot_trafo, another will bechar_list_trafo:onehot_trafois at the moment a three-liner which can at any point be replaced with theonehotmethod in genomelake. I didn't do that to avoid genomelake dependency only because of this functionchar_list_trafoconverts the sequence string returned byFastaReaderinto list of characters, as required by some models.using these definitions, I get a neat and compact defintion of dataloader classes capable to cater for one-hot encoded models with all sorts of different input shapes and axis-order, string-sequece models, etc. see: https://github.com/kipoi/dataloaders/blob/first_draft/kipoi_dataloaders/sequence_based.py. please feel free to take a look at the branch https://github.com/kipoi/dataloaders/tree/first_draft and give feedback :)
krrome commentedon Oct 3, 2018
@lzamparo btw. I am more than happy to use a fasta reading package that has the functionality you requested. pyfaidx does not have the functionality that you have requested - e.g.: requesting the sequence from genomic interval chr15:98503515-98503517 given the fasta example file in your gist in kipoi/kipoi#330. pyfaidx inteprets the entire string after the ">" as a sequence/chromosome name. If you can point me to the fasta reader that you have in mind which is capable to handle this the way you specified and if the that fasta reader complies with the fasta standards then I am more than happy to replace pyfaidx with that one.
This is what happens when I use pyfaidx:
on this fasta file:
lzamparo commentedon Oct 5, 2018
@Avsecz Here's a sample .fasta file in a gist, along with the test interval and expected output
lzamparo commentedon Oct 5, 2018
@krrome I've not used
get_seqbefore, but I used the dict interface ofPyfaidx.Fastato do slicing on Fasta records from a file organized like the one in my original gist you reference.There is one snag, which is you need to convert to relative indexing of the bases from the absolute indexing of the interval, but that's pretty fast. Have a look at the
TruncSeqDatasetdataloader I made, you can see how I'm taking subsequences in__getitem__krrome commentedon Oct 5, 2018
@lzamparo thanks for the link. I could add your way of querying in case the default get_seq throws a
FetchError.. but the problem I can see there is that it will only work if the bed query is matched by a fasta file entry...in any case if your suggestion solves your problem we can add it to the default dataloader, if @Avsecz agrees.
lzamparo commentedon Oct 5, 2018
True, I ensured there would be correspondance by construction. Though I think it can handle the .other common use case, where you have one fasta file per chromosome, and the intervals can be taken as a subset without any conversion to relative sequences. Up to you to decide how to handle the case where an interval has no match in the fasta provided.
Avsecz commentedon Oct 5, 2018
Great! Thanks @lzamparo . I'll have a closer look at your implementation tomorrow and add the provided files to unit-tests.
Update
transformsmodule that contains all the useful pre-processing functions like one-hot encoding, tokenizing or sequence trimming. I re-factored one-hot-encoding functions from concise and also imported the fast one-hot-encoding from genomelake (for the DNA case)lzamparo commentedon Oct 9, 2018
@Avsecz +1 for both transforms you suggest below, I can think of some handy use-cases for both. Also useful might be a random substring transform? I can imagine a scenario when you are working with longer sequences, but the property you're trying to predict is valid over the length of the sequence, and you want to use this for data augmentation.
Avsecz commentedon Oct 9, 2018
@lzamparo what's the motivation of storing chromosome subsets in the fasta file instead of using intervals to query the sequence directly?
Avsecz commentedon Oct 9, 2018
I've started a new issue to keep track of the additional dataloaders: #8. The package is ready and on pypi
pip install kipoiseq. I also created a small colab notebook: link.