diff --git a/planet/extensions.py b/planet/extensions.py index a9344cc..c155d5e 100644 --- a/planet/extensions.py +++ b/planet/extensions.py @@ -6,11 +6,25 @@ from flask_sqlalchemy import SQLAlchemy from flask_whooshee import Whooshee +from sqlalchemy.engine import Engine +from sqlalchemy import event + from planet.flask_blast import BlastThread __all__ = ['db', 'login_manager', 'cache', 'htmlmin', 'blast_thread', 'compress', 'whooshee'] db = SQLAlchemy() + + +@event.listens_for(Engine, "connect") +def set_sqlite_pragma(dbapi_connection, connection_record): + """ + Will force sqlite contraint foreign keys + """ + cursor = dbapi_connection.cursor() + cursor.execute("PRAGMA foreign_keys=ON") + cursor.close() + login_manager = LoginManager() toolbar = DebugToolbarExtension() cache = Cache() diff --git a/planet/models/condition_tissue.py b/planet/models/condition_tissue.py index 39243ee..6df9a77 100644 --- a/planet/models/condition_tissue.py +++ b/planet/models/condition_tissue.py @@ -8,11 +8,13 @@ class ConditionTissue(db.Model): __tablename__ = 'conditions_tissue' id = db.Column(db.Integer, primary_key=True) - species_id = db.Column(db.Integer, db.ForeignKey('species.id')) + species_id = db.Column(db.Integer, db.ForeignKey('species.id', ondelete='CASCADE')) data = db.Column(db.Text) description = db.Column(db.Text) - expression_specificity_method_id = db.Column(db.Integer, db.ForeignKey('expression_specificity_method.id'), index=True) + expression_specificity_method_id = db.Column(db.Integer, + db.ForeignKey('expression_specificity_method.id', ondelete='CASCADE'), + index=True) @staticmethod def add(species_id, data, order, colors, expression_specificity_method_id, description=''): diff --git a/planet/models/expression/coexpression_clusters.py b/planet/models/expression/coexpression_clusters.py index e49a414..5dd3100 100644 --- a/planet/models/expression/coexpression_clusters.py +++ b/planet/models/expression/coexpression_clusters.py @@ -27,14 +27,15 @@ class CoexpressionClusteringMethod(db.Model): __tablename__ = 'coexpression_clustering_methods' id = db.Column(db.Integer, primary_key=True) - network_method_id = db.Column(db.Integer, db.ForeignKey('expression_network_methods.id'), index=True) + network_method_id = db.Column(db.Integer, db.ForeignKey('expression_network_methods.id', ondelete='CASCADE'), index=True) method = db.Column(db.Text) cluster_count = db.Column(db.Integer) clusters = db.relationship('CoexpressionCluster', backref=db.backref('method', lazy='joined'), lazy='dynamic', - cascade='all, delete-orphan') + cascade="all, delete-orphan", + passive_deletes=True) @staticmethod def update_counts(): @@ -334,13 +335,14 @@ def add_lstrap_coexpression_clusters(cluster_file, description, network_id, pref class CoexpressionCluster(db.Model): __tablename__ = 'coexpression_clusters' id = db.Column(db.Integer, primary_key=True) - method_id = db.Column(db.Integer, db.ForeignKey('coexpression_clustering_methods.id')) + method_id = db.Column(db.Integer, db.ForeignKey('coexpression_clustering_methods.id', ondelete='CASCADE')) name = db.Column(db.String(50), index=True) trees = db.relationship('Tree', backref=db.backref('cluster', lazy='joined'), lazy='dynamic', - cascade='all, delete-orphan') + cascade="all, delete-orphan", + passive_deletes=True) # Other properties # sequences defined in Sequence diff --git a/planet/models/expression/networks.py b/planet/models/expression/networks.py index 791236f..6b99770 100644 --- a/planet/models/expression/networks.py +++ b/planet/models/expression/networks.py @@ -30,12 +30,14 @@ class ExpressionNetworkMethod(db.Model): probes = db.relationship('ExpressionNetwork', backref=db.backref('method', lazy='joined'), lazy='dynamic', - cascade='all, delete-orphan') + cascade="all, delete-orphan", + passive_deletes=True) clustering_methods = db.relationship('CoexpressionClusteringMethod', backref='network_method', lazy='dynamic', - cascade='all, delete-orphan') + cascade='all, delete-orphan', + passive_deletes=True) def __init__(self, species_id, description, edge_type="rank"): self.species_id = species_id @@ -251,9 +253,9 @@ class ExpressionNetwork(db.Model): __tablename__ = 'expression_networks' id = db.Column(db.Integer, primary_key=True) probe = db.Column(db.String(50, collation=SQL_COLLATION), index=True) - sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id'), index=True) + sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE'), index=True) network = db.Column(db.Text) - method_id = db.Column(db.Integer, db.ForeignKey('expression_network_methods.id'), index=True) + method_id = db.Column(db.Integer, db.ForeignKey('expression_network_methods.id', ondelete='CASCADE'), index=True) def __init__(self, probe, sequence_id, network, method_id): self.probe = probe diff --git a/planet/models/expression/profiles.py b/planet/models/expression/profiles.py index 21e2408..1e81c57 100644 --- a/planet/models/expression/profiles.py +++ b/planet/models/expression/profiles.py @@ -16,15 +16,16 @@ class ExpressionProfile(db.Model): __tablename__ = 'expression_profiles' id = db.Column(db.Integer, primary_key=True) - species_id = db.Column(db.Integer, db.ForeignKey('species.id'), index=True) + species_id = db.Column(db.Integer, db.ForeignKey('species.id', ondelete='CASCADE'), index=True) probe = db.Column(db.String(50, collation=SQL_COLLATION), index=True) - sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id'), index=True) + sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE'), index=True) profile = db.deferred(db.Column(db.Text)) specificities = db.relationship('ExpressionSpecificity', backref=db.backref('profile', lazy='joined'), lazy='dynamic', - cascade='all, delete-orphan') + cascade="all, delete-orphan", + passive_deletes=True) def __init__(self, probe, sequence_id, profile): self.probe = probe diff --git a/planet/models/expression/specificity.py b/planet/models/expression/specificity.py index a847c3e..ae7ece7 100644 --- a/planet/models/expression/specificity.py +++ b/planet/models/expression/specificity.py @@ -15,15 +15,17 @@ class ExpressionSpecificityMethod(db.Model): id = db.Column(db.Integer, primary_key=True) description = db.Column(db.Text) conditions = db.Column(db.Text) - species_id = db.Column(db.Integer, db.ForeignKey('species.id'), index=True) + species_id = db.Column(db.Integer, db.ForeignKey('species.id', ondelete='CASCADE'), index=True) specificities = db.relationship('ExpressionSpecificity', backref='method', lazy='dynamic', - cascade='all, delete-orphan') + cascade="all, delete-orphan", + passive_deletes=True) condition_tissue = db.relationship('ConditionTissue', backref='expression_specificity_method', lazy='joined', - cascade='all, delete-orphan', uselist=False) + cascade="all, delete-orphan", + passive_deletes=True, uselist=False) menu_order = db.Column(db.Integer) diff --git a/planet/models/gene_families.py b/planet/models/gene_families.py index 90edffc..6217fd4 100644 --- a/planet/models/gene_families.py +++ b/planet/models/gene_families.py @@ -24,7 +24,8 @@ class GeneFamilyMethod(db.Model): families = db.relationship('GeneFamily', backref=db.backref('method', lazy='joined'), lazy='dynamic', - cascade='all, delete-orphan') + cascade="all, delete-orphan", + passive_deletes=True) def __init__(self, method): self.method = method @@ -63,9 +64,9 @@ def add(description): class GeneFamily(db.Model): __tablename__ = 'gene_families' id = db.Column(db.Integer, primary_key=True) - method_id = db.Column(db.Integer, db.ForeignKey('gene_family_methods.id'), index=True) + method_id = db.Column(db.Integer, db.ForeignKey('gene_family_methods.id', ondelete='CASCADE'), index=True) name = db.Column(db.String(50, collation=SQL_COLLATION), unique=True, index=True) - clade_id = db.Column(db.Integer, db.ForeignKey('clades.id'), index=True) + clade_id = db.Column(db.Integer, db.ForeignKey('clades.id', ondelete='SET NULL'), index=True) # Original name is used to keep track of the original ID from OrthoFinder (required to link back to trees) original_name = db.Column(db.String(50, collation=SQL_COLLATION), index=True, default=None) diff --git a/planet/models/go.py b/planet/models/go.py index cac6fb5..c2188c6 100644 --- a/planet/models/go.py +++ b/planet/models/go.py @@ -180,12 +180,19 @@ def add_from_obo(filename, empty=True, compressed=False): obo_parser.extend_go() - for term in obo_parser.terms: + for i, term in enumerate(obo_parser.terms): go = GO(term.id, term.name, term.namespace, term.definition, term.is_obsolete, ";".join(term.is_a), ";".join(term.extended_go)) db.session.add(go) + if i % 40 == 0: + # commit to the db frequently to allow WHOOSHEE's indexing function to work without timing out + try: + db.session.commit() + except Exception as e: + db.session.rollback() + print(e) try: db.session.commit() except Exception as e: diff --git a/planet/models/interpro.py b/planet/models/interpro.py index 0b1e850..bdcfb4f 100644 --- a/planet/models/interpro.py +++ b/planet/models/interpro.py @@ -19,7 +19,7 @@ class Interpro(db.Model): label = db.Column(db.String(50, collation=SQL_COLLATION), unique=True, index=True) description = db.Column(db.Text) - clade_id = db.Column(db.Integer, db.ForeignKey('clades.id'), index=True) + clade_id = db.Column(db.Integer, db.ForeignKey('clades.id', ondelete='SET NULL'), index=True) sequences = db.relationship('Sequence', secondary=sequence_interpro, lazy='dynamic') @@ -141,10 +141,19 @@ def add_from_xml(filename, empty=True): interpro_parser.readfile(filename) - for domain in interpro_parser.domains: + for i, domain in enumerate(interpro_parser.domains): interpro = Interpro(domain.label, domain.description) db.session.add(interpro) + + if i % 40 == 0: + # commit to the db frequently to allow WHOOSHEE's indexing function to work without timing out + try: + db.session.commit() + except Exception as e: + db.session.rollback() + print(e) + try: db.session.commit() except Exception as e: diff --git a/planet/models/relationships/cluster_go.py b/planet/models/relationships/cluster_go.py index c446ea5..b8ff8db 100644 --- a/planet/models/relationships/cluster_go.py +++ b/planet/models/relationships/cluster_go.py @@ -6,17 +6,17 @@ class ClusterGOEnrichment(db.Model): __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) - cluster_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id')) - go_id = db.Column(db.Integer, db.ForeignKey('go.id')) + cluster_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id', ondelete='CASCADE')) + go_id = db.Column(db.Integer, db.ForeignKey('go.id', ondelete='CASCADE')) cluster = db.relationship('CoexpressionCluster', backref=db.backref('go_enrichment', lazy='dynamic', - cascade='all, delete-orphan'), + passive_deletes=True), lazy='joined') go = db.relationship('GO', backref=db.backref('enriched_clusters', lazy='dynamic', - cascade='all, delete-orphan'), + passive_deletes=True), lazy='joined') """ diff --git a/planet/models/relationships/cluster_similarity.py b/planet/models/relationships/cluster_similarity.py index 0a8be33..3c749ed 100644 --- a/planet/models/relationships/cluster_similarity.py +++ b/planet/models/relationships/cluster_similarity.py @@ -6,10 +6,10 @@ class CoexpressionClusterSimilarity(db.Model): __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) - source_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id')) - target_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id')) + source_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id', ondelete='CASCADE')) + target_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id', ondelete='CASCADE')) - gene_family_method_id = db.Column('gene_family_method_id', db.Integer, db.ForeignKey('gene_family_methods.id'), + gene_family_method_id = db.Column('gene_family_method_id', db.Integer, db.ForeignKey('gene_family_methods.id', ondelete='CASCADE'), index=True) jaccard_index = db.Column(db.Float, index=True) @@ -18,15 +18,17 @@ class CoexpressionClusterSimilarity(db.Model): source = db.relationship('CoexpressionCluster', backref=db.backref('similarity_sources', lazy='dynamic', - cascade='all, delete-orphan'), + passive_deletes=True), lazy='joined', foreign_keys=[source_id]) target = db.relationship('CoexpressionCluster', backref=db.backref('similarity_targets', lazy='dynamic', - cascade='all, delete-orphan') + passive_deletes=True) , lazy='joined', foreign_keys=[target_id]) - gene_family_method = db.relationship('GeneFamilyMethod', lazy='joined') + gene_family_method = db.relationship('GeneFamilyMethod', + backref=db.backref('CoexpressionClusterSimilarities', passive_deletes=True), + lazy='joined') @staticmethod def empty_table(): diff --git a/planet/models/relationships/family_xref.py b/planet/models/relationships/family_xref.py index 46f0319..5c1b67a 100644 --- a/planet/models/relationships/family_xref.py +++ b/planet/models/relationships/family_xref.py @@ -6,5 +6,5 @@ class FamilyXRefAssociation(db.Model): __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) - gene_family_id = db.Column(db.Integer, db.ForeignKey('gene_families.id')) - xref_id = db.Column(db.Integer, db.ForeignKey('xrefs.id')) + gene_family_id = db.Column(db.Integer, db.ForeignKey('gene_families.id', ondelete='CASCADE')) + xref_id = db.Column(db.Integer, db.ForeignKey('xrefs.id', ondelete='CASCADE')) diff --git a/planet/models/relationships/sequence_cluster.py b/planet/models/relationships/sequence_cluster.py index 4111a9d..b5ed924 100644 --- a/planet/models/relationships/sequence_cluster.py +++ b/planet/models/relationships/sequence_cluster.py @@ -7,15 +7,15 @@ class SequenceCoexpressionClusterAssociation(db.Model): id = db.Column(db.Integer, primary_key=True) probe = db.Column(db.String(50), index=True) - sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id')) - coexpression_cluster_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id')) + sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE')) + coexpression_cluster_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id', ondelete='CASCADE')) sequence = db.relationship('Sequence', backref=db.backref('coexpression_cluster_associations', lazy='dynamic', - cascade="all, delete-orphan"), + passive_deletes=True), lazy='joined') coexpression_cluster = db.relationship('CoexpressionCluster', backref=db.backref('sequence_associations', lazy='dynamic', - cascade="all, delete-orphan"), + passive_deletes=True), lazy='joined') \ No newline at end of file diff --git a/planet/models/relationships/sequence_family.py b/planet/models/relationships/sequence_family.py index 74c8648..226e7fd 100644 --- a/planet/models/relationships/sequence_family.py +++ b/planet/models/relationships/sequence_family.py @@ -6,14 +6,14 @@ class SequenceFamilyAssociation(db.Model): __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) - sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id')) - gene_family_id = db.Column(db.Integer, db.ForeignKey('gene_families.id')) + sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE')) + gene_family_id = db.Column(db.Integer, db.ForeignKey('gene_families.id', ondelete='CASCADE')) sequence = db.relationship('Sequence', backref=db.backref('family_associations', lazy='dynamic', - cascade='all, delete-orphan'), lazy='joined') + passive_deletes=True), lazy='joined') family = db.relationship('GeneFamily', backref=db.backref('sequence_associations', lazy='dynamic', - cascade='all, delete-orphan'), lazy='joined') + passive_deletes=True), lazy='joined') diff --git a/planet/models/relationships/sequence_go.py b/planet/models/relationships/sequence_go.py index b460d05..c77e514 100644 --- a/planet/models/relationships/sequence_go.py +++ b/planet/models/relationships/sequence_go.py @@ -6,8 +6,8 @@ class SequenceGOAssociation(db.Model): __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) - sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id')) - go_id = db.Column(db.Integer, db.ForeignKey('go.id')) + sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE')) + go_id = db.Column(db.Integer, db.ForeignKey('go.id', ondelete='CASCADE')) evidence = db.Column(db.Enum('EXP', 'IDA', 'IPI', 'IMP', 'IGI', 'IEP', 'ISS', 'ISO', 'ISA', 'ISM', 'IGC', 'IBA', 'IBD', 'IKR', 'IRD', 'RCA', @@ -16,8 +16,8 @@ class SequenceGOAssociation(db.Model): sequence = db.relationship('Sequence', backref=db.backref('go_associations', lazy='dynamic', - cascade='all, delete-orphan'), lazy='joined') + passive_deletes=True), lazy='joined') go = db.relationship('GO', backref=db.backref('sequence_associations', lazy='dynamic', - cascade='all, delete-orphan'), lazy='joined') \ No newline at end of file + passive_deletes=True), lazy='joined') \ No newline at end of file diff --git a/planet/models/relationships/sequence_interpro.py b/planet/models/relationships/sequence_interpro.py index 905351d..2a6661d 100644 --- a/planet/models/relationships/sequence_interpro.py +++ b/planet/models/relationships/sequence_interpro.py @@ -6,14 +6,14 @@ class SequenceInterproAssociation(db.Model): __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) - sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id')) - interpro_id = db.Column(db.Integer, db.ForeignKey('interpro.id')) + sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE')) + interpro_id = db.Column(db.Integer, db.ForeignKey('interpro.id', ondelete='CASCADE')) start = db.Column(db.Integer, default=None) stop = db.Column(db.Integer, default=None) sequence = db.relationship('Sequence', backref=db.backref('interpro_associations', lazy='dynamic', - cascade='all, delete-orphan'), lazy='joined') + passive_deletes=True), lazy='joined') domain = db.relationship('Interpro', backref=db.backref('sequence_associations', - lazy='dynamic', cascade='all, delete-orphan'), lazy='joined') + lazy='dynamic', passive_deletes=True), lazy='joined') diff --git a/planet/models/relationships/sequence_sequence_ecc.py b/planet/models/relationships/sequence_sequence_ecc.py index 001d233..08fe8e3 100644 --- a/planet/models/relationships/sequence_sequence_ecc.py +++ b/planet/models/relationships/sequence_sequence_ecc.py @@ -12,21 +12,21 @@ class SequenceSequenceECCAssociation(db.Model): id = db.Column(db.Integer, primary_key=True) - query_id = db.Column(db.Integer, db.ForeignKey('sequences.id')) - target_id = db.Column(db.Integer, db.ForeignKey('sequences.id')) + query_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE')) + target_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE')) ecc = db.Column(db.Float) p_value = db.Column(db.Float) corrected_p_value = db.Column(db.Float) - gene_family_method_id = db.Column(db.Integer, db.ForeignKey('gene_family_methods.id')) - query_network_method_id = db.Column(db.Integer, db.ForeignKey('expression_network_methods.id')) - target_network_method_id = db.Column(db.Integer, db.ForeignKey('expression_network_methods.id')) + gene_family_method_id = db.Column(db.Integer, db.ForeignKey('gene_family_methods.id', ondelete='CASCADE')) + query_network_method_id = db.Column(db.Integer, db.ForeignKey('expression_network_methods.id', ondelete='CASCADE')) + target_network_method_id = db.Column(db.Integer, db.ForeignKey('expression_network_methods.id', ondelete='CASCADE')) gene_family_method = db.relationship('GeneFamilyMethod', lazy='joined', backref=db.backref('ecc_as_family_method', lazy='dynamic', - cascade='all, delete-orphan') + passive_deletes=True) ) query_expression_network_method = db.relationship('ExpressionNetworkMethod', @@ -34,14 +34,14 @@ class SequenceSequenceECCAssociation(db.Model): lazy='joined', backref=db.backref('ecc_as_query_method', lazy='dynamic', - cascade='all, delete-orphan') + passive_deletes=True) ) target_expression_network_method = db.relationship('ExpressionNetworkMethod', foreign_keys=[target_network_method_id], lazy='joined', backref=db.backref('ecc_as_target_method', lazy='dynamic', - cascade='all, delete-orphan') + passive_deletes=True) ) @staticmethod diff --git a/planet/models/relationships/sequence_xref.py b/planet/models/relationships/sequence_xref.py index 870b446..17d7a85 100644 --- a/planet/models/relationships/sequence_xref.py +++ b/planet/models/relationships/sequence_xref.py @@ -6,5 +6,5 @@ class SequenceXRefAssociation(db.Model): __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) - sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id')) - xref_id = db.Column(db.Integer, db.ForeignKey('xrefs.id')) + sequence_id = db.Column(db.Integer, db.ForeignKey('sequences.id', ondelete='CASCADE')) + xref_id = db.Column(db.Integer, db.ForeignKey('xrefs.id', ondelete='CASCADE')) diff --git a/planet/models/sequences.py b/planet/models/sequences.py index 74ec335..183b3ad 100644 --- a/planet/models/sequences.py +++ b/planet/models/sequences.py @@ -15,7 +15,7 @@ class Sequence(db.Model): __tablename__ = 'sequences' id = db.Column(db.Integer, primary_key=True) - species_id = db.Column(db.Integer, db.ForeignKey('species.id'), index=True) + species_id = db.Column(db.Integer, db.ForeignKey('species.id', ondelete='CASCADE'), index=True) name = db.Column(db.String(50, collation=SQL_COLLATION), index=True) description = db.Column(db.Text) coding_sequence = db.deferred(db.Column(db.Text)) @@ -25,8 +25,13 @@ class Sequence(db.Model): expression_profiles = db.relationship('ExpressionProfile', backref=db.backref('sequence', lazy='joined'), lazy='dynamic', - cascade='all, delete-orphan') - network_nodes = db.relationship('ExpressionNetwork', backref='sequence', lazy='dynamic') + cascade="all, delete-orphan", + passive_deletes=True) + network_nodes = db.relationship('ExpressionNetwork', + backref='sequence', + lazy='dynamic', + cascade="all, delete-orphan", + passive_deletes=True) # Other properties # diff --git a/planet/models/species.py b/planet/models/species.py index 27702f9..ebc5224 100644 --- a/planet/models/species.py +++ b/planet/models/species.py @@ -16,11 +16,11 @@ class Species(db.Model): profile_count = db.Column(db.Integer) description = db.Column(db.Text) - sequences = db.relationship('Sequence', backref='species', lazy='dynamic', cascade='all, delete-orphan') - networks = db.relationship('ExpressionNetworkMethod', backref='species', lazy='dynamic', cascade='all, delete-orphan') - profiles = db.relationship('ExpressionProfile', backref='species', lazy='dynamic', cascade='all, delete-orphan') - expression_specificities = db.relationship('ExpressionSpecificityMethod', backref='species', lazy='dynamic', cascade='all, delete-orphan') - condition_tissues = db.relationship('ConditionTissue', backref='species', lazy='dynamic', cascade='all, delete-orphan') + sequences = db.relationship('Sequence', backref='species', lazy='dynamic', cascade="all, delete-orphan",passive_deletes=True) + networks = db.relationship('ExpressionNetworkMethod', backref='species', lazy='dynamic', cascade="all, delete-orphan",passive_deletes=True) + profiles = db.relationship('ExpressionProfile', backref='species', lazy='dynamic', cascade="all, delete-orphan",passive_deletes=True) + expression_specificities = db.relationship('ExpressionSpecificityMethod', backref='species', lazy='dynamic', cascade="all, delete-orphan",passive_deletes=True) + condition_tissues = db.relationship('ConditionTissue', backref='species', lazy='dynamic', cascade="all, delete-orphan",passive_deletes=True) def __init__(self, code, name, data_type='genome', color="#C7C7C7", highlight="#DEDEDE", description=None): diff --git a/planet/models/trees.py b/planet/models/trees.py index ab88a57..8925474 100644 --- a/planet/models/trees.py +++ b/planet/models/trees.py @@ -10,13 +10,14 @@ class TreeMethod(db.Model): description = db.Column(db.Text) coexpression_clustering_method_id = db.Column(db.Integer, - db.ForeignKey('coexpression_clustering_methods.id'), + db.ForeignKey('coexpression_clustering_methods.id', ondelete='CASCADE'), index=True) trees = db.relationship('Tree', backref=db.backref('method', lazy='joined'), lazy='dynamic', - cascade='all, delete-orphan') + cascade="all, delete-orphan", + passive_deletes=True) class Tree(db.Model): @@ -27,5 +28,5 @@ class Tree(db.Model): data_newick = db.Column(db.Text) data_phyloxml = db.Column(db.Text) - method_id = db.Column(db.Integer, db.ForeignKey('tree_methods.id'), index=True) - cluster_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id'), index=True) + method_id = db.Column(db.Integer, db.ForeignKey('tree_methods.id', ondelete='CASCADE'), index=True) + cluster_id = db.Column(db.Integer, db.ForeignKey('coexpression_clusters.id', ondelete='CASCADE'), index=True) diff --git a/tests/admin.py b/tests/admin.py index 21c0937..0dda00f 100644 --- a/tests/admin.py +++ b/tests/admin.py @@ -16,7 +16,10 @@ '/admin/add/interpro/', '/admin/add/clades/', '/admin/add/xrefs/', '/admin/add/xrefs_families/', '/admin/controls/', '/admin/species/', '/admin/clades/', '/admin/families/', '/admin/networks/', '/admin/clusters/', '/admin/specificity/', - '/admin/condition_tissue/', '/admin/add/functional_data/', '/admin/add/sequence_descriptions/'] + '/admin/condition_tissue/', '/admin/add/functional_data/', '/admin/add/sequence_descriptions/', + '/admin_controls/update/counts', '/admin_controls/update/clades', '/admin/build/ecc/', + '/admin/build/cluster_similarities/', '/admin/build/go_enrichment', '/admin/build/hcca_clusters/', + '/admin/build/neighborhood_to_clusters/'] class AdminTest(TestCase): @@ -65,6 +68,7 @@ def test_admin_views_as_admin(self): for required_endpoint in required_endpoints: response = self.client.get(required_endpoint, follow_redirects=True) + # print(required_endpoint) self.assert200(response) @unittest.skipIf(not LOGIN_ENABLED, "Skipping test_admin_views because LOGIN is not enabled") @@ -261,6 +265,10 @@ def test_admin_controls(self): self.assert200(response) self.assertTrue('All clades updated' in response.data.decode('utf-8')) # Check for flash message + response = self.client.get('/admin_controls/update/clades', follow_redirects=True) + self.assert200(response) + self.assertTrue('All clades updated' in response.data.decode('utf-8')) # Check for flash message + response = self.client.get('/admin_controls/export_ftp', follow_redirects=True) self.assert200(response) self.assertTrue('Successfully exported data to FTP folder' in response.data.decode('utf-8')) # Check for flash message diff --git a/tests/website.py b/tests/website.py index 06bff7b..4946d76 100644 --- a/tests/website.py +++ b/tests/website.py @@ -75,9 +75,11 @@ def setUp(self): test_sequence.go_labels.append(test_go) test_sequence2 = Sequence(test_species.id, 'TEST_SEQ_02', 'ATG', description='test sequence') - + test_sequence3 = Sequence(test_species.id, 'TEST_SEQ_03', 'ATG', description='test sequence') + test_sequence3.type = 'TE'; db.session.add(test_sequence) db.session.add(test_sequence2) + db.session.add(test_sequence3) db.session.commit() test_profile = ExpressionProfile('test_probe', test_sequence.id, '{"data": {"seedling - hypocotyl 17d": [29.0, 44.0, 35.0], "stage 15 flower - pedicel +21d": [39.0, 18.0, 28.0], "senescing leaf 35d": [104.0, 95.0, 121.0], "stage 12 flower - stamen +21d": [56.0, 41.0, 40.0], "seed - triangle stage 56d": [18.0, 21.0, 37.0], "pollen - uninuclear stage": [17.0, 17.0], "seed - globular stage 56d": [17.0, 28.0, 25.0], "root 21d": [49000.0, 46000.0, 49000.0], "stage 12 flower - carpel +21d": [29.0, 34.0, 38.0], "quiescent center and endodermis, beyond the mature hair zone": [5.0, 5.0, 17.0], "stage 12 flower +21d": [26.0, 39.0, 41.0], "mature seed 56d": [14.0, 12.0, 11.0], "shoot 21d": [94.0, 63.0, 75.0], "stage 10 flower +21d": [83.0, 112.0, 99.0], "stage 12 flower - petal +21d": [68.0, 57.0, 47.0], "seed - heart stage 56d": [44.0, 39.0, 17.0], "stage 1 flower 21d": [126.0, 120.0, 116.0], "stem 2nd internode +21d": [41.0, 42.0, 41.0], "pollen stage 10 - pollen sac 42d": [22.0, 46.0, 31.0], "endodermis, cortex and quiescent center": [13.0, 20.0, 13.0], "rosette leaf 10d": [40.0, 27.0, 44.0], "root 17d": [44.0, 53.0, 51.0], "stage 12 flower - sepal +21d": [56.0, 39.0, 53.0], "stage 9 flower +21d": [113.0, 107.0, 143.0], "~0.15 mm from the root tip": [58.0, 35.0, 17.0, 15.0], "stage 15 flower - carpel +21d": [33.0, 22.0, 24.0], "~0.30 mm from the root tip": [13.0, 13.0, 24.0, 66.0], "rosette leaf - distal half 17d": [18.0, 25.0, 20.0], "petiole 17d": [28.0, 19.0, 20.0], "pollen - bicellular stage": [26.0, 16.0], "atrichoblasts from the quiescent center up": [7.0, 20.0, 8.0], "~0.45 to 2 mm from the root tip": [0.0, 23.0, 20.0, 3.0], "complete rosette 22d": [19.0, 29.0, 24.0], "pollen - tricellular stage": [22.0, 32.0], "stem 1st internode +21d": [72.0, 78.0, 63.0], "stage 15 flower +21d": [32.0, 38.0, 39.0], "pollen - mature": [31.0, 46.0, 22.0], "cauline leaf +21d": [58.0, 41.0, 51.0], "seedling - shoot apex 7d": [27.0, 23.0, 43.0], "complete rosette 23d": [21.0, 20.0, 20.0], "seedling - rosette leaf 7d": [42.0, 40.0, 33.0], "complete rosette 21d": [21.0, 26.0, 22.0], "rosette leaf 17d": [62.0, 57.0, 29.0], "seed - torpedo stage 56d": [24.0, 32.0, 23.0], "rosette leaf - proximal half 17d": [26.0, 17.0, 21.0], "seedling - cotyledon 7d": [50.0, 31.0, 25.0], "stage 15 flower - stamen +21d": [30.0, 18.0, 28.0], "root stele to elongation zone": [20.0, 9.0, 11.0], "stage 15 flower - sepal +21d": [49.0, 28.0, 22.0], "stage 15 flower - petal +21d": [30.0, 19.0, 45.0], "seed - curled cotyledon stage 56d": [16.0, 15.0, 15.0], "lateral root cap and epidermis": [12.0, 6.0, 5.0]}, "order": ["seedling - cotyledon 7d", "seedling - hypocotyl 17d", "seedling - rosette leaf 7d", "seedling - shoot apex 7d", "root 17d", "root 21d", "~0.15 mm from the root tip", "~0.30 mm from the root tip", "~0.45 to 2 mm from the root tip", "atrichoblasts from the quiescent center up", "endodermis, cortex and quiescent center", "lateral root cap and epidermis", "quiescent center and endodermis, beyond the mature hair zone", "root stele to elongation zone", "rosette leaf 10d", "rosette leaf 17d", "rosette leaf - distal half 17d", "rosette leaf - proximal half 17d", "complete rosette 21d", "complete rosette 22d", "complete rosette 23d", "senescing leaf 35d", "cauline leaf +21d", "petiole 17d", "shoot 21d", "stem 1st internode +21d", "stem 2nd internode +21d", "stage 1 flower 21d", "stage 9 flower +21d", "stage 10 flower +21d", "stage 12 flower - carpel +21d", "stage 12 flower - petal +21d", "stage 12 flower - sepal +21d", "stage 12 flower - stamen +21d", "stage 12 flower +21d", "stage 15 flower - carpel +21d", "stage 15 flower - pedicel +21d", "stage 15 flower - petal +21d", "stage 15 flower - sepal +21d", "stage 15 flower - stamen +21d", "stage 15 flower +21d", "seed - curled cotyledon stage 56d", "seed - globular stage 56d", "seed - heart stage 56d", "seed - torpedo stage 56d", "seed - triangle stage 56d", "mature seed 56d", "pollen stage 10 - pollen sac 42d", "pollen - uninuclear stage", "pollen - bicellular stage", "pollen - tricellular stage", "pollen - mature"]}') @@ -248,6 +250,9 @@ def test_sequence(self): sequence = Sequence.query.first() + response = self.client.get("/sequence/") + self.assertRedirects(response, '/') + response = self.client.get("/sequence/view/%d" % sequence.id) self.assert_template_used('sequence.html') self.assert200(response) @@ -256,6 +261,14 @@ def test_sequence(self): self.assert_template_used('tooltips/sequence.html') self.assert200(response) + response = self.client.get("/sequence/modal/coding/%d" % sequence.id) + self.assert_template_used('modals/sequence.html') + self.assert200(response) + + response = self.client.get("/sequence/modal/protein/%d" % sequence.id) + self.assert_template_used('modals/sequence.html') + self.assert200(response) + response = self.client.get("/sequence/fasta/coding/%d" % sequence.id) self.assert200(response) data = response.data.decode("utf-8").strip() @@ -625,6 +638,14 @@ def test_search(self): self.assertTrue('value' in d.keys()) self.assertTrue('tokens' in d.keys()) + def test_advanced_search(self): + """ + Test different components of the search function + """ + response = self.client.get('/search/advanced') + self.assert200(response) + self.assert_template_used('search_advanced.html') + @unittest.skipIf(not LOGIN_ENABLED, "Skipping test_auth because LOGIN is not enabled") def test_auth(self): """ @@ -688,6 +709,17 @@ def test_heatmap(self): self.assert_template_used('expression_heatmap.html') self.assert200(response) + response = self.client.get('/heatmap/inchlib/j/%d.json' % cluster.id) + self.assert200(response) + data = json.loads(response.data.decode('utf-8')) + self.assertTrue("data" in data.keys()) + self.assertTrue("nodes" in data["data"]) + self.assertTrue("feature_names" in data["data"]) + + response = self.client.get('/heatmap/inchlib/%d' % cluster.id) + self.assert_template_used('inchlib_heatmap.html') + self.assert200(response) + def test_profile_comparison(self): from planet.models.expression.profiles import ExpressionProfile from planet.models.expression.coexpression_clusters import CoexpressionCluster