emjun / tisane

Specification language for generating Generalized Linear Models (with or without mixed effects) from conceptual models
Apache License 2.0
21 stars 3 forks source link

Graph created from a Design is empty #23

Closed audreyseo closed 3 years ago

audreyseo commented 3 years ago

For example, if we take the following code:

    def test_more_complex(self):
        student = ts.Unit(
            "Student", attributes=[]
        )  # object type, specify data types through object type
        race = student.nominal("Race", cardinality=5, exactly=1)  # proper OOP
        ses = student.numeric("SES")
        test_score = student.nominal("Test score")
        tutoring = student.nominal("treatment")
        race.associates_with(test_score)
        student.associates_with(test_score)
        race.moderate(ses, on=test_score)
        design = ts.Design(dv=test_score, ivs=[race, ses])
        gr = design.graph
        print(gr.get_nodes())
        self.assertTrue(gr.has_variable(test_score))

the print will print an empty list, and the assertion will fail. This seems to be because graph.py requires relationships from tisane.og_variable instead of from tisane.variable, and tisane.design calls tisane.graph.Graph.add_relationship to add edges:

# from tisane/graph.py
    def add_relationship(
        self, relationship: Union[Has, Treatment, Nest, Associate, Cause, Moderate]
    ):
        if isinstance(relationship, Has):
            identifier = relationship.variable
            measure = relationship.measure
            repetitions = relationship.repetitions
            self.has(identifier, measure, relationship, repetitions)
        elif isinstance(relationship, Treatment):
            identifier = relationship.unit
            treatment = relationship.treatment
            repetitions = relationship.num_assignments
            self.treat(unit=identifier, treatment=treatment, treatment_obj=relationship)
        # ...

The types for relationship are imported from tisane.og_variable, which means that none of the relationships are added as edges.

audreyseo commented 3 years ago

Changing the imports on tisane/graph.py has helped, like so:

from tisane.og_variable import (
    # AbstractVariable,
    Nominal,
    Ordinal,
    Numeric,
    # Unit,
    Treatment,
    # Nest,
    RepeatedMeasure,
    # Has,
    # Associate,
    # Cause,
    # Moderate,
    GreaterThanOne,
)
from tisane.variable import (
    Measure,
    Unit,
    AbstractVariable,
    Has,
    Associates,
    Causes,
    Moderates,
    Nests
)

I'm just not sure if I'm breaking anything by doing so.

emjun commented 3 years ago

ts.og_variable was a temporary hack I had used to test a few tests for API changes.

Since commit, this is no longer a bug. The graph has all the expected variables and edges. This means that this program:

        student = ts.Unit("Student")
        # Variables instantiated through Units
        race = student.nominal("Race", cardinality=5)
        ses = student.numeric("SES")
        test_score = student.numeric("Test score")
        tutoring = student.nominal("treatment", cardinality=3)

has the following nodes/passes the below tests that were failing before:

        self.assertTrue(gr.has_variable(student))
        self.assertTrue(gr.has_variable(race))
        self.assertTrue(gr.has_variable(ses))
        self.assertTrue(gr.has_variable(test_score))
        self.assertFalse(gr.has_variable(tutoring))

See test_graph.py for the above test case.