Dear Simon,
thanks again for your kind help.
Actually the creation of new instances is not intended. But I'm not getting
where they are created...
I give you more insight:
This is the scheduler object with the associated propagate() method
class Scheduler(six.with_metaclass(abc.ABCMeta)):
""" This class gets a list of GroundStation objects and a list of
Satellites
objects and compute all the passages of the Satellites over the
GroundStations
Args:
sat_list(list): List of Satellites objects
gs_list(list): List of GroundStation objects
start_day(datetime): The datetime object representing the day from
which to start the propagation
time_of_propagation(int): Number of hours to propagate
[default:24]
deltaT(float): Time step to use for angles retrieval, in seconds
"""
def __init__(self, sat_list, gs_list, start_day, time_of_propagation=24,
deltaT=0.05):
# Monkey patch the Satellite class with the cost_function specific
# of the scheduler algorithm.
sat_class = type(sat_list[0])
sat_class.cost_function = self.cost_function
self.sat_list = sat_list
self.gs_list = gs_list
self.start_day = start_day
self.time_of_propagation = time_of_propagation
self.deltaT = deltaT
def propagate(self):
""" This method computes all the passages of the Satellites over the
GroundStations
Args:
Returns:
all_passages(PassageList): A list ordered from the earliest
passage\
of all passages
Raises:
ModelNotAvailable: When a satellite is too far from Earth and
the
models available in Orbital are not good, a
ModelNotAvailable is
raised
"""
all_passages = PassageList()
# Loop Over the gs list
for gs in self.gs_list:
# Loop over the satellites list
for sat in self.sat_list:
# Compute all the passages in the specified period
passages = \
sat.get_next_passes(gs, self.start_day,
self.time_of_propagation,
deltaT=self.deltaT)
# Unfolding the list of passages in a flat list
all_passages = all_passages + passages
return all_passages
It just basically loops over all the ground station and satellites and
generates all the passages. Maybe the fact that I monkey patch the
satellite class induces the creation of a new instance of `Satellite`?
The details of the `get_next_passes` method of the `Satellite` class for
what concerns the `Passage` instance creation, skipping the algorithmic
part, are:
def _generate_passage(self, next_pass, ground_station, deltaT):
""" This method returns a Passage Object from the data returned from
the original Orbital.get_next_passes method.
"""
aos, los, tca = next_pass
return Passage(satellite=self,
ground_station=ground_station,
aos=aos, los=los, tca=tca,
deltaT=deltaT)
`self` should be a reference to the instance of `Satellite` already loaded
from DB. I will try to dive more into the code...
Thanks a lot for the kind help of all of you,
On Monday, January 15, 2018 at 10:06:24 AM UTC+1, Simon King wrote:
>
> On Sat, Jan 13, 2018 at 3:31 PM, Ruben Di Battista
> <[email protected] <javascript:>> wrote:
> >
> >
> > On Friday, January 12, 2018 at 10:54:49 AM UTC+1, Simon King wrote:
> >>
> >> If I understand your code correctly, scheduler.propagate() creates a
> >> large number of Passage instances, and you only want a small subset of
> >> them to be added to the database. Is that correct?
> >
> >
> > Correct!
> >
> >>
> >> I would guess that the passages are getting added to the session
> >> because you are setting their 'satellite' property to point to a
> >> Satellite which is already in the database. This then causes the
> >> passages to be added to the session due to the default cascade rules
> >> on the relationship
> >> (http://docs.sqlalchemy.org/en/latest/orm/cascades.html).
> >>
> >> If that really is the case, you can change the cascade rules for that
> >> relationship, and then you'll probably need to explicitly add the
> >> passages you want to *keep* to the session instead.
> >>
> >> Hope that helps,
> >>
> >> Simon
> >
> >
> > Dear Simon,
> > thank you. That was the case. Modifying the cascade disabling the
> backref
> > cascade does not load in the DB the passages at propagation time.
> >
> > But now, when I manually add the subset of passages after the
> optimization,
> > I get a:
> >
> > InvalidRequestError: Can't attach instance <Satellite at 0x108c4dfd0>;
> > another instance with key [...] is already present in this section.
> >
> > So, I suppose that disabling the backref cascade now SQLAlchemy is not
> > capable anymore to recognize the already loaded Satellite objects...
> >
> > Should I maybe merge somewhere?
> >
>
> It sounds like your propagate() function is creating new Satellite
> instances with the same primary key as instances that have been loaded
> from the database. Merging is one way to avoid that, and the
> UniqueObject pattern is another. It's difficult to say which is more
> appropriate for your usage without seeing more code. But if
> propagate() is only supposed to be calculating passages, I don't
> understand why new Satellites are being created at all - shouldn't all
> the Satellites already be loaded?
>
> Simon
>
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
http://www.sqlalchemy.org/
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable
Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.