[Gmod-ajax] Filter VCF by SnpEff Impact?

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

[Gmod-ajax] Filter VCF by SnpEff Impact?

Richard Hayes
Hi,

I have a plugin under development that reads VCF data from a webservice rather than VCFTabix access. It is similar in structure to CanvasVariants, subclassing CanvasFeatures and replacing parsing etc from Store/SeqFeature/VCFTabix with custom ajax calls.

We would like to add track display filters based on SnpEff impact in addition to the FILTER column. I am having trouble unpacking how filter functions operate fully.

Specifically, I can't successfully access INFO column fields from within the anonymous functions that are submitted to makeFilterFilter in _VariantDetailMixin.js. I think I can alter my custom Parser to add associated impacts to featureData.filter values and add these to the vcfHeader data. It looks like a click on a track menu filter compares the filtername to values in each featureData.filter, so this might be sufficient.

Any suggestions? Has anyone else tried tackling a custom feature filter in JBrowse?

Thanks,

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Colin
There is actually an easier interface to create filters, which is available for all track types, than the ones that are for VCF that you mentioned. The VCF ones sort of automatically create a filter from attributes in the VCF file itself, but you can invent your own filters using the addFeatureFilter function which comes from src/JBrowse/FeatureFilterMixin.js

Example

The addFeatureFilter is available on all track objects so it should be easy to access from your plugin. Another fun fact is that the browser object itself also has these functions available, which will apply to filters to all tracks.

-Colin

On Mon, May 8, 2017 at 10:58 PM, Richard Hayes <[hidden email]> wrote:
Hi,

I have a plugin under development that reads VCF data from a webservice rather than VCFTabix access. It is similar in structure to CanvasVariants, subclassing CanvasFeatures and replacing parsing etc from Store/SeqFeature/VCFTabix with custom ajax calls.

We would like to add track display filters based on SnpEff impact in addition to the FILTER column. I am having trouble unpacking how filter functions operate fully.

Specifically, I can't successfully access INFO column fields from within the anonymous functions that are submitted to makeFilterFilter in _VariantDetailMixin.js. I think I can alter my custom Parser to add associated impacts to featureData.filter values and add these to the vcfHeader data. It looks like a click on a track menu filter compares the filtername to values in each featureData.filter, so this might be sufficient.

Any suggestions? Has anyone else tried tackling a custom feature filter in JBrowse?

Thanks,

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Richard Hayes
Hi,

Thanks, I like this approach. I am having trouble getting the filter to activate. What is the source of the feat object in the

     thisB.addFeatureFilter(function(feat) {

call like line 21 of your example?

I am also seeing my _trackMenuOptions() running twice in chrome dev tools as the track loads, so that is obviously the potential fault. I'm not sure how to trace the caller. The Caller stack looks the same in both instances.

I have these after an empty constructo()  and _defaultConfig() in my View/Track/<tracktype>.js code

        _trackMenuOptions: function() {
            return all([ this.inherited(arguments), this._snpeffImpactFilterTrackMenuOptions(), this._variantsFilterTrackMenuOptions() ])
                .then( function( options ) {
                    var o = options.shift();
                    options.unshift( { type: 'dijit/MenuSeparator' } );
                    return o.concat.apply( o, options );
            });
        },

        _snpeffImpactFilterTrackMenuOptions: function() {
        var opts = [];
            var thisB = this;
            var impactList = ["HIGH", "MODERATE", "LOW", "MODIFIER"];
            for( var i in impactList ) {
                var filterName = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: function() {
                        if(this.checked) {
                            thisB.addFeatureFilter(function(feat) {
                                console.log(feat);
                                var effArray = feat.get('EFF');
                                if( effArray &&  typeof effArray == 'object' && 'values' in effArray )
                                    effArray = effArray.values;
                                if( effArray && ! lang.isArray( effArray ) )
                                    effArray = [effArray];
                                if (! effArray)
                                    return false;
                                var thisTest = new RegExp(filterName);
                                for ( var i in effArray ) {
                                    var line = effArray[i];
                                    if ( line.match( thisTest ) ) {
                                        return true;
                                    }
                                }
                                return false;
                            }, 'snpeff_'+filterName);
                        }
                        else {
                            thisB.removeFeatureFilter('snpeff_'+filterName);
                        }
                    }
                });
            }
            opts.push( { type: 'dijit/MenuSeparator' } );
            return opts;
        }


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Mon, May 8, 2017 at 8:14 PM, Colin <[hidden email]> wrote:
There is actually an easier interface to create filters, which is available for all track types, than the ones that are for VCF that you mentioned. The VCF ones sort of automatically create a filter from attributes in the VCF file itself, but you can invent your own filters using the addFeatureFilter function which comes from src/JBrowse/FeatureFilterMixin.js

Example

The addFeatureFilter is available on all track objects so it should be easy to access from your plugin. Another fun fact is that the browser object itself also has these functions available, which will apply to filters to all tracks.

-Colin

On Mon, May 8, 2017 at 10:58 PM, Richard Hayes <[hidden email]> wrote:
Hi,

I have a plugin under development that reads VCF data from a webservice rather than VCFTabix access. It is similar in structure to CanvasVariants, subclassing CanvasFeatures and replacing parsing etc from Store/SeqFeature/VCFTabix with custom ajax calls.

We would like to add track display filters based on SnpEff impact in addition to the FILTER column. I am having trouble unpacking how filter functions operate fully.

Specifically, I can't successfully access INFO column fields from within the anonymous functions that are submitted to makeFilterFilter in _VariantDetailMixin.js. I think I can alter my custom Parser to add associated impacts to featureData.filter values and add these to the vcfHeader data. It looks like a click on a track menu filter compares the filtername to values in each featureData.filter, so this might be sufficient.

Any suggestions? Has anyone else tried tackling a custom feature filter in JBrowse?

Thanks,

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax




------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Colin
>What is the source of the feat object in the ... call like line 21 of your example?

That is a callback function and feat is passed in automatically to it :) (e.g. similar to how I might have style.color = function(feat) { ... }

-Colin

PS I'm not sure about the function being called twice, I think i can see that happening as well, but menu construction still seems normal


On Wed, May 10, 2017 at 4:10 PM, Richard Hayes <[hidden email]> wrote:
Hi,

Thanks, I like this approach. I am having trouble getting the filter to activate. What is the source of the feat object in the

     thisB.addFeatureFilter(function(feat) {

call like line 21 of your example?

I am also seeing my _trackMenuOptions() running twice in chrome dev tools as the track loads, so that is obviously the potential fault. I'm not sure how to trace the caller. The Caller stack looks the same in both instances.

I have these after an empty constructo()  and _defaultConfig() in my View/Track/<tracktype>.js code

        _trackMenuOptions: function() {
            return all([ this.inherited(arguments), this._snpeffImpactFilterTrackMenuOptions(), this._variantsFilterTrackMenuOptions() ])
                .then( function( options ) {
                    var o = options.shift();
                    options.unshift( { type: 'dijit/MenuSeparator' } );
                    return o.concat.apply( o, options );
            });
        },

        _snpeffImpactFilterTrackMenuOptions: function() {
        var opts = [];
            var thisB = this;
            var impactList = ["HIGH", "MODERATE", "LOW", "MODIFIER"];
            for( var i in impactList ) {
                var filterName = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: function() {
                        if(this.checked) {
                            thisB.addFeatureFilter(function(feat) {
                                console.log(feat);
                                var effArray = feat.get('EFF');
                                if( effArray &&  typeof effArray == 'object' && 'values' in effArray )
                                    effArray = effArray.values;
                                if( effArray && ! lang.isArray( effArray ) )
                                    effArray = [effArray];
                                if (! effArray)
                                    return false;
                                var thisTest = new RegExp(filterName);
                                for ( var i in effArray ) {
                                    var line = effArray[i];
                                    if ( line.match( thisTest ) ) {
                                        return true;
                                    }
                                }
                                return false;
                            }, 'snpeff_'+filterName);
                        }
                        else {
                            thisB.removeFeatureFilter('snpeff_'+filterName);
                        }
                    }
                });
            }
            opts.push( { type: 'dijit/MenuSeparator' } );
            return opts;
        }


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Mon, May 8, 2017 at 8:14 PM, Colin <[hidden email]> wrote:
There is actually an easier interface to create filters, which is available for all track types, than the ones that are for VCF that you mentioned. The VCF ones sort of automatically create a filter from attributes in the VCF file itself, but you can invent your own filters using the addFeatureFilter function which comes from src/JBrowse/FeatureFilterMixin.js

Example

The addFeatureFilter is available on all track objects so it should be easy to access from your plugin. Another fun fact is that the browser object itself also has these functions available, which will apply to filters to all tracks.

-Colin

On Mon, May 8, 2017 at 10:58 PM, Richard Hayes <[hidden email]> wrote:
Hi,

I have a plugin under development that reads VCF data from a webservice rather than VCFTabix access. It is similar in structure to CanvasVariants, subclassing CanvasFeatures and replacing parsing etc from Store/SeqFeature/VCFTabix with custom ajax calls.

We would like to add track display filters based on SnpEff impact in addition to the FILTER column. I am having trouble unpacking how filter functions operate fully.

Specifically, I can't successfully access INFO column fields from within the anonymous functions that are submitted to makeFilterFilter in _VariantDetailMixin.js. I think I can alter my custom Parser to add associated impacts to featureData.filter values and add these to the vcfHeader data. It looks like a click on a track menu filter compares the filtername to values in each featureData.filter, so this might be sufficient.

Any suggestions? Has anyone else tried tackling a custom feature filter in JBrowse?

Thanks,

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax





------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Richard Hayes
Yes, my four menu items are added before the defaults based on the FILTER header as intended, but have no effect. Do I have the logic correct otherwise?

- return true to include in the view
- return false to exclude from the view
- default to true

My intention is a checkbox to remove any matches to that impact level.

Thanks!


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 2:21 PM, Colin <[hidden email]> wrote:
>What is the source of the feat object in the ... call like line 21 of your example?

That is a callback function and feat is passed in automatically to it :) (e.g. similar to how I might have style.color = function(feat) { ... }

-Colin

PS I'm not sure about the function being called twice, I think i can see that happening as well, but menu construction still seems normal


On Wed, May 10, 2017 at 4:10 PM, Richard Hayes <[hidden email]> wrote:
Hi,

Thanks, I like this approach. I am having trouble getting the filter to activate. What is the source of the feat object in the

     thisB.addFeatureFilter(function(feat) {

call like line 21 of your example?

I am also seeing my _trackMenuOptions() running twice in chrome dev tools as the track loads, so that is obviously the potential fault. I'm not sure how to trace the caller. The Caller stack looks the same in both instances.

I have these after an empty constructo()  and _defaultConfig() in my View/Track/<tracktype>.js code

        _trackMenuOptions: function() {
            return all([ this.inherited(arguments), this._snpeffImpactFilterTrackMenuOptions(), this._variantsFilterTrackMenuOptions() ])
                .then( function( options ) {
                    var o = options.shift();
                    options.unshift( { type: 'dijit/MenuSeparator' } );
                    return o.concat.apply( o, options );
            });
        },

        _snpeffImpactFilterTrackMenuOptions: function() {
        var opts = [];
            var thisB = this;
            var impactList = ["HIGH", "MODERATE", "LOW", "MODIFIER"];
            for( var i in impactList ) {
                var filterName = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: function() {
                        if(this.checked) {
                            thisB.addFeatureFilter(function(feat) {
                                console.log(feat);
                                var effArray = feat.get('EFF');
                                if( effArray &&  typeof effArray == 'object' && 'values' in effArray )
                                    effArray = effArray.values;
                                if( effArray && ! lang.isArray( effArray ) )
                                    effArray = [effArray];
                                if (! effArray)
                                    return false;
                                var thisTest = new RegExp(filterName);
                                for ( var i in effArray ) {
                                    var line = effArray[i];
                                    if ( line.match( thisTest ) ) {
                                        return true;
                                    }
                                }
                                return false;
                            }, 'snpeff_'+filterName);
                        }
                        else {
                            thisB.removeFeatureFilter('snpeff_'+filterName);
                        }
                    }
                });
            }
            opts.push( { type: 'dijit/MenuSeparator' } );
            return opts;
        }


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Mon, May 8, 2017 at 8:14 PM, Colin <[hidden email]> wrote:
There is actually an easier interface to create filters, which is available for all track types, than the ones that are for VCF that you mentioned. The VCF ones sort of automatically create a filter from attributes in the VCF file itself, but you can invent your own filters using the addFeatureFilter function which comes from src/JBrowse/FeatureFilterMixin.js

Example

The addFeatureFilter is available on all track objects so it should be easy to access from your plugin. Another fun fact is that the browser object itself also has these functions available, which will apply to filters to all tracks.

-Colin

On Mon, May 8, 2017 at 10:58 PM, Richard Hayes <[hidden email]> wrote:
Hi,

I have a plugin under development that reads VCF data from a webservice rather than VCFTabix access. It is similar in structure to CanvasVariants, subclassing CanvasFeatures and replacing parsing etc from Store/SeqFeature/VCFTabix with custom ajax calls.

We would like to add track display filters based on SnpEff impact in addition to the FILTER column. I am having trouble unpacking how filter functions operate fully.

Specifically, I can't successfully access INFO column fields from within the anonymous functions that are submitted to makeFilterFilter in _VariantDetailMixin.js. I think I can alter my custom Parser to add associated impacts to featureData.filter values and add these to the vcfHeader data. It looks like a click on a track menu filter compares the filtername to values in each featureData.filter, so this might be sufficient.

Any suggestions? Has anyone else tried tackling a custom feature filter in JBrowse?

Thanks,

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax






------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Richard Hayes
Trick question, as my code snippet had these reversed. Though, neither direction is working for me.

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 2:27 PM, Richard Hayes <[hidden email]> wrote:
Yes, my four menu items are added before the defaults based on the FILTER header as intended, but have no effect. Do I have the logic correct otherwise?

- return true to include in the view
- return false to exclude from the view
- default to true

My intention is a checkbox to remove any matches to that impact level.

Thanks!


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 2:21 PM, Colin <[hidden email]> wrote:
>What is the source of the feat object in the ... call like line 21 of your example?

That is a callback function and feat is passed in automatically to it :) (e.g. similar to how I might have style.color = function(feat) { ... }

-Colin

PS I'm not sure about the function being called twice, I think i can see that happening as well, but menu construction still seems normal


On Wed, May 10, 2017 at 4:10 PM, Richard Hayes <[hidden email]> wrote:
Hi,

Thanks, I like this approach. I am having trouble getting the filter to activate. What is the source of the feat object in the

     thisB.addFeatureFilter(function(feat) {

call like line 21 of your example?

I am also seeing my _trackMenuOptions() running twice in chrome dev tools as the track loads, so that is obviously the potential fault. I'm not sure how to trace the caller. The Caller stack looks the same in both instances.

I have these after an empty constructo()  and _defaultConfig() in my View/Track/<tracktype>.js code

        _trackMenuOptions: function() {
            return all([ this.inherited(arguments), this._snpeffImpactFilterTrackMenuOptions(), this._variantsFilterTrackMenuOptions() ])
                .then( function( options ) {
                    var o = options.shift();
                    options.unshift( { type: 'dijit/MenuSeparator' } );
                    return o.concat.apply( o, options );
            });
        },

        _snpeffImpactFilterTrackMenuOptions: function() {
        var opts = [];
            var thisB = this;
            var impactList = ["HIGH", "MODERATE", "LOW", "MODIFIER"];
            for( var i in impactList ) {
                var filterName = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: function() {
                        if(this.checked) {
                            thisB.addFeatureFilter(function(feat) {
                                console.log(feat);
                                var effArray = feat.get('EFF');
                                if( effArray &&  typeof effArray == 'object' && 'values' in effArray )
                                    effArray = effArray.values;
                                if( effArray && ! lang.isArray( effArray ) )
                                    effArray = [effArray];
                                if (! effArray)
                                    return false;
                                var thisTest = new RegExp(filterName);
                                for ( var i in effArray ) {
                                    var line = effArray[i];
                                    if ( line.match( thisTest ) ) {
                                        return true;
                                    }
                                }
                                return false;
                            }, 'snpeff_'+filterName);
                        }
                        else {
                            thisB.removeFeatureFilter('snpeff_'+filterName);
                        }
                    }
                });
            }
            opts.push( { type: 'dijit/MenuSeparator' } );
            return opts;
        }


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Mon, May 8, 2017 at 8:14 PM, Colin <[hidden email]> wrote:
There is actually an easier interface to create filters, which is available for all track types, than the ones that are for VCF that you mentioned. The VCF ones sort of automatically create a filter from attributes in the VCF file itself, but you can invent your own filters using the addFeatureFilter function which comes from src/JBrowse/FeatureFilterMixin.js

Example

The addFeatureFilter is available on all track objects so it should be easy to access from your plugin. Another fun fact is that the browser object itself also has these functions available, which will apply to filters to all tracks.

-Colin

On Mon, May 8, 2017 at 10:58 PM, Richard Hayes <[hidden email]> wrote:
Hi,

I have a plugin under development that reads VCF data from a webservice rather than VCFTabix access. It is similar in structure to CanvasVariants, subclassing CanvasFeatures and replacing parsing etc from Store/SeqFeature/VCFTabix with custom ajax calls.

We would like to add track display filters based on SnpEff impact in addition to the FILTER column. I am having trouble unpacking how filter functions operate fully.

Specifically, I can't successfully access INFO column fields from within the anonymous functions that are submitted to makeFilterFilter in _VariantDetailMixin.js. I think I can alter my custom Parser to add associated impacts to featureData.filter values and add these to the vcfHeader data. It looks like a click on a track menu filter compares the filtername to values in each featureData.filter, so this might be sufficient.

Any suggestions? Has anyone else tried tackling a custom feature filter in JBrowse?

Thanks,

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax







------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Colin
Hmm I think I forgot that you also should call track.redraw() too after adding filter



-Colin

On Wed, May 10, 2017 at 5:28 PM, Richard Hayes <[hidden email]> wrote:
Trick question, as my code snippet had these reversed. Though, neither direction is working for me.

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 2:27 PM, Richard Hayes <[hidden email]> wrote:
Yes, my four menu items are added before the defaults based on the FILTER header as intended, but have no effect. Do I have the logic correct otherwise?

- return true to include in the view
- return false to exclude from the view
- default to true

My intention is a checkbox to remove any matches to that impact level.

Thanks!


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 2:21 PM, Colin <[hidden email]> wrote:
>What is the source of the feat object in the ... call like line 21 of your example?

That is a callback function and feat is passed in automatically to it :) (e.g. similar to how I might have style.color = function(feat) { ... }

-Colin

PS I'm not sure about the function being called twice, I think i can see that happening as well, but menu construction still seems normal


On Wed, May 10, 2017 at 4:10 PM, Richard Hayes <[hidden email]> wrote:
Hi,

Thanks, I like this approach. I am having trouble getting the filter to activate. What is the source of the feat object in the

     thisB.addFeatureFilter(function(feat) {

call like line 21 of your example?

I am also seeing my _trackMenuOptions() running twice in chrome dev tools as the track loads, so that is obviously the potential fault. I'm not sure how to trace the caller. The Caller stack looks the same in both instances.

I have these after an empty constructo()  and _defaultConfig() in my View/Track/<tracktype>.js code

        _trackMenuOptions: function() {
            return all([ this.inherited(arguments), this._snpeffImpactFilterTrackMenuOptions(), this._variantsFilterTrackMenuOptions() ])
                .then( function( options ) {
                    var o = options.shift();
                    options.unshift( { type: 'dijit/MenuSeparator' } );
                    return o.concat.apply( o, options );
            });
        },

        _snpeffImpactFilterTrackMenuOptions: function() {
        var opts = [];
            var thisB = this;
            var impactList = ["HIGH", "MODERATE", "LOW", "MODIFIER"];
            for( var i in impactList ) {
                var filterName = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: function() {
                        if(this.checked) {
                            thisB.addFeatureFilter(function(feat) {
                                console.log(feat);
                                var effArray = feat.get('EFF');
                                if( effArray &&  typeof effArray == 'object' && 'values' in effArray )
                                    effArray = effArray.values;
                                if( effArray && ! lang.isArray( effArray ) )
                                    effArray = [effArray];
                                if (! effArray)
                                    return false;
                                var thisTest = new RegExp(filterName);
                                for ( var i in effArray ) {
                                    var line = effArray[i];
                                    if ( line.match( thisTest ) ) {
                                        return true;
                                    }
                                }
                                return false;
                            }, 'snpeff_'+filterName);
                        }
                        else {
                            thisB.removeFeatureFilter('snpeff_'+filterName);
                        }
                    }
                });
            }
            opts.push( { type: 'dijit/MenuSeparator' } );
            return opts;
        }


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Mon, May 8, 2017 at 8:14 PM, Colin <[hidden email]> wrote:
There is actually an easier interface to create filters, which is available for all track types, than the ones that are for VCF that you mentioned. The VCF ones sort of automatically create a filter from attributes in the VCF file itself, but you can invent your own filters using the addFeatureFilter function which comes from src/JBrowse/FeatureFilterMixin.js

Example

The addFeatureFilter is available on all track objects so it should be easy to access from your plugin. Another fun fact is that the browser object itself also has these functions available, which will apply to filters to all tracks.

-Colin

On Mon, May 8, 2017 at 10:58 PM, Richard Hayes <[hidden email]> wrote:
Hi,

I have a plugin under development that reads VCF data from a webservice rather than VCFTabix access. It is similar in structure to CanvasVariants, subclassing CanvasFeatures and replacing parsing etc from Store/SeqFeature/VCFTabix with custom ajax calls.

We would like to add track display filters based on SnpEff impact in addition to the FILTER column. I am having trouble unpacking how filter functions operate fully.

Specifically, I can't successfully access INFO column fields from within the anonymous functions that are submitted to makeFilterFilter in _VariantDetailMixin.js. I think I can alter my custom Parser to add associated impacts to featureData.filter values and add these to the vcfHeader data. It looks like a click on a track menu filter compares the filtername to values in each featureData.filter, so this might be sufficient.

Any suggestions? Has anyone else tried tackling a custom feature filter in JBrowse?

Thanks,

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax








------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Richard Hayes
That did alter behavior, in that I can now track the anon function calls in the chrome debugger, but now the checkboxes don't update and I still don't see filter activity in my test region. Apologies that I'm behind a firewall here...

First, is the filter paradigm that returning true would retain a feature, or apply the filter? This is a bit unclear.

It seems that my example filter function is at fault, too. I'm seeing

     return true

fire off for every feature in that example, whether the test is

     if ( line.match( thisTest ) ) {

or

     if ( line.search( thisTest ) != -1 ) {

as this first loops on MODIFIER and that is almost always true in an EFF annotation when I'm clicking on the filter for HIGH, for example.

How can I access the filter name in this function to make sure I only return true here testing the requested filter that matches the particular impact?


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 2:37 PM, Colin <[hidden email]> wrote:
Hmm I think I forgot that you also should call track.redraw() too after adding filter



-Colin

On Wed, May 10, 2017 at 5:28 PM, Richard Hayes <[hidden email]> wrote:
Trick question, as my code snippet had these reversed. Though, neither direction is working for me.

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 2:27 PM, Richard Hayes <[hidden email]> wrote:
Yes, my four menu items are added before the defaults based on the FILTER header as intended, but have no effect. Do I have the logic correct otherwise?

- return true to include in the view
- return false to exclude from the view
- default to true

My intention is a checkbox to remove any matches to that impact level.

Thanks!


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 2:21 PM, Colin <[hidden email]> wrote:
>What is the source of the feat object in the ... call like line 21 of your example?

That is a callback function and feat is passed in automatically to it :) (e.g. similar to how I might have style.color = function(feat) { ... }

-Colin

PS I'm not sure about the function being called twice, I think i can see that happening as well, but menu construction still seems normal


On Wed, May 10, 2017 at 4:10 PM, Richard Hayes <[hidden email]> wrote:
Hi,

Thanks, I like this approach. I am having trouble getting the filter to activate. What is the source of the feat object in the

     thisB.addFeatureFilter(function(feat) {

call like line 21 of your example?

I am also seeing my _trackMenuOptions() running twice in chrome dev tools as the track loads, so that is obviously the potential fault. I'm not sure how to trace the caller. The Caller stack looks the same in both instances.

I have these after an empty constructo()  and _defaultConfig() in my View/Track/<tracktype>.js code

        _trackMenuOptions: function() {
            return all([ this.inherited(arguments), this._snpeffImpactFilterTrackMenuOptions(), this._variantsFilterTrackMenuOptions() ])
                .then( function( options ) {
                    var o = options.shift();
                    options.unshift( { type: 'dijit/MenuSeparator' } );
                    return o.concat.apply( o, options );
            });
        },

        _snpeffImpactFilterTrackMenuOptions: function() {
        var opts = [];
            var thisB = this;
            var impactList = ["HIGH", "MODERATE", "LOW", "MODIFIER"];
            for( var i in impactList ) {
                var filterName = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: function() {
                        if(this.checked) {
                            thisB.addFeatureFilter(function(feat) {
                                console.log(feat);
                                var effArray = feat.get('EFF');
                                if( effArray &&  typeof effArray == 'object' && 'values' in effArray )
                                    effArray = effArray.values;
                                if( effArray && ! lang.isArray( effArray ) )
                                    effArray = [effArray];
                                if (! effArray)
                                    return false;
                                var thisTest = new RegExp(filterName);
                                for ( var i in effArray ) {
                                    var line = effArray[i];
                                    if ( line.match( thisTest ) ) {
                                        return true;
                                    }
                                }
                                return false;
                            }, 'snpeff_'+filterName);
                        }
                        else {
                            thisB.removeFeatureFilter('snpeff_'+filterName);
                        }
                    }
                });
            }
            opts.push( { type: 'dijit/MenuSeparator' } );
            return opts;
        }


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Mon, May 8, 2017 at 8:14 PM, Colin <[hidden email]> wrote:
There is actually an easier interface to create filters, which is available for all track types, than the ones that are for VCF that you mentioned. The VCF ones sort of automatically create a filter from attributes in the VCF file itself, but you can invent your own filters using the addFeatureFilter function which comes from src/JBrowse/FeatureFilterMixin.js

Example

The addFeatureFilter is available on all track objects so it should be easy to access from your plugin. Another fun fact is that the browser object itself also has these functions available, which will apply to filters to all tracks.

-Colin

On Mon, May 8, 2017 at 10:58 PM, Richard Hayes <[hidden email]> wrote:
Hi,

I have a plugin under development that reads VCF data from a webservice rather than VCFTabix access. It is similar in structure to CanvasVariants, subclassing CanvasFeatures and replacing parsing etc from Store/SeqFeature/VCFTabix with custom ajax calls.

We would like to add track display filters based on SnpEff impact in addition to the FILTER column. I am having trouble unpacking how filter functions operate fully.

Specifically, I can't successfully access INFO column fields from within the anonymous functions that are submitted to makeFilterFilter in _VariantDetailMixin.js. I think I can alter my custom Parser to add associated impacts to featureData.filter values and add these to the vcfHeader data. It looks like a click on a track menu filter compares the filtername to values in each featureData.filter, so this might be sufficient.

Any suggestions? Has anyone else tried tackling a custom feature filter in JBrowse?

Thanks,

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax









------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Richard Hayes
Is there a method that accesses the uniqName of the filter that is running?

thisB._featureFilterChain[0].name

is also always evaluating as snpeff_MODIFIER when I click on the HIGH checkbox.

Ironically, thisB._getFeatureFilterName() gives me "feature_1" through "feature_135" instead of anything related to the current feature.

​I'm thinking I can add a check for uniqName, as passed to addFeatureFilter as the second param, to the regexp testing and be sure that we are matching the requested impact.





------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Colin
You may be running into a common javascript problem, which is that the variable outside the closure (the filter name) does not get bound inside your closure (your filter callback).

You can fix this using something like this


            for( var i in impactList ) {
                var ff = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: (function(filterName) { return function() {
                        /* use filterName like normal here */
                    })(ff)
                });
            }

The onClick function is now called an IIFE https://developer.mozilla.org/en-US/docs/Glossary/IIFE which just serves to "bind" the impactList[i] variable to the callback



-Colin

On Wed, May 10, 2017 at 7:37 PM, Richard Hayes <[hidden email]> wrote:
Is there a method that accesses the uniqName of the filter that is running?

thisB._featureFilterChain[0].name

is also always evaluating as snpeff_MODIFIER when I click on the HIGH checkbox.

Ironically, thisB._getFeatureFilterName() gives me "feature_1" through "feature_135" instead of anything related to the current feature.

​I'm thinking I can add a check for uniqName, as passed to addFeatureFilter as the second param, to the regexp testing and be sure that we are matching the requested impact.






------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Richard Hayes
Ah, that helps, thanks.

I set that up and my new test is now

    if ( filterName.search( thisTest) != -1 && line.search( thisTest ) != -1 ) {
        return false;
    }

and true otherwise. This now hides sites with the selected annotation. But the menu is not redrawn in checked state and I can't revert the filter once applied.

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 4:50 PM, Colin <[hidden email]> wrote:
You may be running into a common javascript problem, which is that the variable outside the closure (the filter name) does not get bound inside your closure (your filter callback).

You can fix this using something like this


            for( var i in impactList ) {
                var ff = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: (function(filterName) { return function() {
                        /* use filterName like normal here */
                    })(ff)
                });
            }

The onClick function is now called an IIFE https://developer.mozilla.org/en-US/docs/Glossary/IIFE which just serves to "bind" the impactList[i] variable to the callback



-Colin

On Wed, May 10, 2017 at 7:37 PM, Richard Hayes <[hidden email]> wrote:
Is there a method that accesses the uniqName of the filter that is running?

thisB._featureFilterChain[0].name

is also always evaluating as snpeff_MODIFIER when I click on the HIGH checkbox.

Ironically, thisB._getFeatureFilterName() gives me "feature_1" through "feature_135" instead of anything related to the current feature.

​I'm thinking I can add a check for uniqName, as passed to addFeatureFilter as the second param, to the regexp testing and be sure that we are matching the requested impact.







------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Colin
Looks like that was a bug in the example I posted again. I think if you track the checkbox state like this then it maybe that can fix it :)

diff --git a/js/View/Track/FilterTrack.js b/js/View/Track/FilterTrack.js
index b48e894..1f24074 100644
--- a/js/View/Track/FilterTrack.js
+++ b/js/View/Track/FilterTrack.js
@@ -16,6 +16,7 @@ function(
             opts.push({
                 label: "Add high quality filter?",
                 type: "dijit/CheckedMenuItem",
+                checked: !!this.config.filterEnabled,
                 onClick: function() {
                     if(this.checked) {
                         thisB.addFeatureFilter(function(feat) {
@@ -25,6 +26,7 @@ function(
                     else {
                         thisB.removeFeatureFilter('myfilter');
                     }
+                    thisB.config.filterEnabled = this.checked;
                     thisB.redraw();
                 }
             });




-Colin

On Wed, May 10, 2017 at 8:22 PM, Richard Hayes <[hidden email]> wrote:
Ah, that helps, thanks.

I set that up and my new test is now

    if ( filterName.search( thisTest) != -1 && line.search( thisTest ) != -1 ) {
        return false;
    }

and true otherwise. This now hides sites with the selected annotation. But the menu is not redrawn in checked state and I can't revert the filter once applied.

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 4:50 PM, Colin <[hidden email]> wrote:
You may be running into a common javascript problem, which is that the variable outside the closure (the filter name) does not get bound inside your closure (your filter callback).

You can fix this using something like this


            for( var i in impactList ) {
                var ff = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: (function(filterName) { return function() {
                        /* use filterName like normal here */
                    })(ff)
                });
            }

The onClick function is now called an IIFE https://developer.mozilla.org/en-US/docs/Glossary/IIFE which just serves to "bind" the impactList[i] variable to the callback



-Colin

On Wed, May 10, 2017 at 7:37 PM, Richard Hayes <[hidden email]> wrote:
Is there a method that accesses the uniqName of the filter that is running?

thisB._featureFilterChain[0].name

is also always evaluating as snpeff_MODIFIER when I click on the HIGH checkbox.

Ironically, thisB._getFeatureFilterName() gives me "feature_1" through "feature_135" instead of anything related to the current feature.

​I'm thinking I can add a check for uniqName, as passed to addFeatureFilter as the second param, to the regexp testing and be sure that we are matching the requested impact.








------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax
Reply | Threaded
Open this post in threaded view
|

Re: Filter VCF by SnpEff Impact?

Richard Hayes
Okay, thanks a lot for that. It's unclear what is set by the framework and inheritance and what needs to be explicitly tracked. One more bug fix: I had to use thisB.config.filterEnabled throughout.

I also turned thisB.config.filterEnabled into a simple object to be able to track multiple impact filters this way. I might need to fiddle with the filter function logic, but this is working for me now:

        _trackMenuOptions: function() {
                return all([ this.inherited(arguments), this._snpeffImpactFilterTrackMenuOptions(), this._variantsFilterTrackMenuOptions() ])
                .then( function( options ) {
                    var o = options.shift();
                    options.unshift( { type: 'dijit/MenuSeparator' } );
                    return o.concat.apply( o, options );
                    });
        },

        _snpeffImpactFilterTrackMenuOptions: function() {
            var opts = [];
            var thisB = this;
            var impactList = ["HIGH", "MODERATE", "LOW", "MODIFIER"];
            for( var i in impactList ) {
                var filterName = impactList[i];
                if (!(thisB.config.filterEnabled))
                    thisB.config.filterEnabled = {};
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: !!thisB.config.filterEnabled[filterName],
                    onClick: (function(filterName){ return function() {
                        if(this.checked) {
                            thisB.addFeatureFilter(function(feat) {
                                var effArray = feat.get('EFF');
                                if( effArray &&  typeof effArray == 'object' && 'values' in effArray )
                                    effArray = effArray.values;
                                if( effArray && ! lang.isArray( effArray ) )
                                    effArray = [effArray];
                                if (! effArray)
                                    return true;
                                var thisTest = new RegExp(filterName);
                                for ( var i in effArray ) {
                                    var line = effArray[i];
                                    if ( filterName.search( thisTest) != -1 && line.search( thisTest ) != -1 ) {
                                        return false;
                                    }
                                }
                                return true;
                            }, 'snpeff_'+filterName);
                        }
                        else {
                            thisB.removeFeatureFilter('snpeff_'+filterName);
                        }
                        thisB.config.filterEnabled[filterName] = this.checked;
                        thisB.redraw();
                    }})(filterName)
                });
            }
            opts.push( { type: 'dijit/MenuSeparator' } );
            return opts;
        }


Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 6:46 PM, Colin <[hidden email]> wrote:
Looks like that was a bug in the example I posted again. I think if you track the checkbox state like this then it maybe that can fix it :)

diff --git a/js/View/Track/FilterTrack.js b/js/View/Track/FilterTrack.js
index b48e894..1f24074 100644
--- a/js/View/Track/FilterTrack.js
+++ b/js/View/Track/FilterTrack.js
@@ -16,6 +16,7 @@ function(
             opts.push({
                 label: "Add high quality filter?",
                 type: "dijit/CheckedMenuItem",
+                checked: !!this.config.filterEnabled,
                 onClick: function() {
                     if(this.checked) {
                         thisB.addFeatureFilter(function(feat) {
@@ -25,6 +26,7 @@ function(
                     else {
                         thisB.removeFeatureFilter('myfilter');
                     }
+                    thisB.config.filterEnabled = this.checked;
                     thisB.redraw();
                 }
             });




-Colin

On Wed, May 10, 2017 at 8:22 PM, Richard Hayes <[hidden email]> wrote:
Ah, that helps, thanks.

I set that up and my new test is now

    if ( filterName.search( thisTest) != -1 && line.search( thisTest ) != -1 ) {
        return false;
    }

and true otherwise. This now hides sites with the selected annotation. But the menu is not redrawn in checked state and I can't revert the filter once applied.

Richard D. Hayes, Ph.D.
Joint Genome Institute / Lawrence Berkeley National Lab
http://phytozome.jgi.doe.gov

On Wed, May 10, 2017 at 4:50 PM, Colin <[hidden email]> wrote:
You may be running into a common javascript problem, which is that the variable outside the closure (the filter name) does not get bound inside your closure (your filter callback).

You can fix this using something like this


            for( var i in impactList ) {
                var ff = impactList[i];
                opts.push({
                    label: 'Hide sites with SnpEff IMPACT "'+filterName+'"',
                    type: "dijit/CheckedMenuItem",
                    checked: false,
                    onClick: (function(filterName) { return function() {
                        /* use filterName like normal here */
                    })(ff)
                });
            }

The onClick function is now called an IIFE https://developer.mozilla.org/en-US/docs/Glossary/IIFE which just serves to "bind" the impactList[i] variable to the callback



-Colin

On Wed, May 10, 2017 at 7:37 PM, Richard Hayes <[hidden email]> wrote:
Is there a method that accesses the uniqName of the filter that is running?

thisB._featureFilterChain[0].name

is also always evaluating as snpeff_MODIFIER when I click on the HIGH checkbox.

Ironically, thisB._getFeatureFilterName() gives me "feature_1" through "feature_135" instead of anything related to the current feature.

​I'm thinking I can add a check for uniqName, as passed to addFeatureFilter as the second param, to the regexp testing and be sure that we are matching the requested impact.









------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Gmod-ajax mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gmod-ajax