1 package CXGN
::Pedigree
::AddCrosses
;
5 CXGN::Pedigree::AddCrosses - a module to add cross experiments.
9 my $cross_add = CXGN::Pedigree::AddCrosses->new({ schema => $schema, location => $location_name, program => $program_name, crosses => \@array_of_pedigree_objects} );
10 my $validated = $cross_add->validate_crosses(); #is true when all of the crosses are valid and the accessions they point to exist in the database.
11 $cross_add->add_crosses();
15 Adds an array of crosses. The stock names used in the cross must already exist in the database, and the verify function does this check. This module is intended to be used in independent loading scripts and interactive dialogs.
19 Jeremy D. Edwards (jde22@cornell.edu)
24 use MooseX
::FollowPBP
;
25 use Moose
::Util
::TypeConstraints
;
27 use Bio
::GeneticRelationships
::Pedigree
;
28 use Bio
::GeneticRelationships
::Individual
;
29 use CXGN
::Stock
::StockLookup
;
30 use CXGN
::Location
::LocationLookup
;
31 use CXGN
::BreedersToolbox
::Projects
;
33 use CXGN
::Trial
::Folder
;
34 use SGN
::Model
::Cvterm
;
36 class_type
'Pedigree', { class => 'Bio::GeneticRelationships::Pedigree' };
37 has
'chado_schema' => (
39 isa
=> 'DBIx::Class::Schema',
40 predicate
=> 'has_chado_schema',
43 has
'phenome_schema' => (
45 isa
=> 'DBIx::Class::Schema',
46 predicate
=> 'has_phenome_schema',
49 has
'metadata_schema' => (
51 isa
=> 'DBIx::Class::Schema',
52 predicate
=> 'has_metadata_schema',
55 has
'dbh' => (is
=> 'rw',predicate
=> 'has_dbh', required
=> 1,);
56 has
'crosses' => (isa
=>'ArrayRef[Pedigree]', is
=> 'rw', predicate
=> 'has_crosses', required
=> 1,);
57 has
'location' => (isa
=>'Str', is
=> 'rw', predicate
=> 'has_location', required
=> 1,);
58 has
'program' => (isa
=>'Str', is
=> 'rw', predicate
=> 'has_program', required
=> 1,);
59 has
'owner_name' => (isa
=> 'Str', is
=> 'rw', predicate
=> 'has_owner_name', required
=> 1,);
60 has
'parent_folder_id' => (isa
=> 'Str', is
=> 'rw', predicate
=> 'has_parent_folder_id', required
=> 0,);
64 my $chado_schema = $self->get_chado_schema();
65 my $phenome_schema = $self->get_phenome_schema();
71 my $transaction_error;
76 my $owner_name = $self->get_owner_name();
77 $parent_folder_id = $self->get_parent_folder_id() || 0;
78 my $dbh = $self->get_dbh();
79 my $owner_sp_person_id = CXGN
::People
::Person
->get_person_by_username($dbh, $owner_name); #add person id as an option.
81 if (!$self->validate_crosses()) {
82 print STDERR
"Invalid pedigrees in array. No crosses will be added\n";
86 #add all crosses in a single transaction
89 #get cvterms for parents and offspring
90 my $female_parent_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'female_parent', 'stock_relationship');
92 my $male_parent_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'male_parent', 'stock_relationship');
93 my $progeny_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'offspring_of', 'stock_relationship');
95 #get cvterm for cross_name or create if not found
96 my $cross_name_cvterm = $chado_schema->resultset("Cv::Cvterm")
100 if (!$cross_name_cvterm) {
101 $cross_name_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'cross_name', 'nd_experiment_property');
103 #get cvterm for cross_type or create if not found
104 my $cross_type_cvterm = $chado_schema->resultset("Cv::Cvterm")
106 name
=> 'cross_type',
109 if (!$cross_type_cvterm) {
110 $cross_type_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'cross_type', 'nd_experiment_property');
113 #get cvterm for cross_experiment
114 my $cross_experiment_type_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'cross_experiment', 'experiment_type');
116 #get cvterm for stock type cross
117 my $cross_stock_type_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'cross', 'stock_type');
119 print STDERR
"\n\ncvterm from addcrosses: ".$cross_stock_type_cvterm->cvterm_id()."\n\n";
121 #lookup location by name
122 $location_lookup = CXGN
::Location
::LocationLookup
->new({ schema
=> $chado_schema, location_name
=> $self->get_location });
123 $geolocation = $location_lookup->get_geolocation();
125 #lookup program by name
126 $program_lookup = CXGN
::BreedersToolbox
::Projects
->new({ schema
=> $chado_schema});
127 $program = $program_lookup->get_breeding_program_by_name($self->get_program());
129 @crosses = @
{$self->get_crosses()};
131 foreach my $pedigree (@crosses) {
135 my $female_parent_name;
136 my $male_parent_name;
139 my $population_stock;
141 my $cross_type = $pedigree->get_cross_type();
142 my $cross_name = $pedigree->get_name();
144 if ($pedigree->has_female_parent()) {
145 $female_parent_name = $pedigree->get_female_parent()->get_name();
146 $female_parent = $self->_get_accession($female_parent_name);
149 if ($pedigree->has_male_parent()) {
150 $male_parent_name = $pedigree->get_male_parent()->get_name();
151 $male_parent = $self->_get_accession($male_parent_name);
154 #organism of cross experiment will be the same as the female parent
155 if ($female_parent) {
156 $organism_id = $female_parent->organism_id();
158 $organism_id = $male_parent->organism_id();
161 #create cross project
162 $project = $chado_schema->resultset('Project::Project')
165 description
=> $cross_name,
168 #add error if cross name exists
170 #add cross to folder if one was specified
171 if ($parent_folder_id) {
172 my $folder = CXGN
::Trial
::Folder
->new(
174 bcs_schema
=> $chado_schema,
175 folder_id
=> $project->project_id(),
178 $folder->associate_parent($parent_folder_id);
181 #set projectprop so that projects corresponding to crosses can be identified
182 my $prop_row = $chado_schema->resultset("Project::Projectprop")
184 type_id
=> $cross_stock_type_cvterm->cvterm_id,
185 project_id
=> $project->project_id(),
189 #create cross experiment
190 $experiment = $chado_schema->resultset('NaturalDiversity::NdExperiment')->create(
192 nd_geolocation_id
=> $geolocation->nd_geolocation_id(),
193 type_id
=> $cross_experiment_type_cvterm->cvterm_id(),
196 #store the cross name as an experiment prop
197 $experiment->find_or_create_related('nd_experimentprops' , {
198 nd_experiment_id
=> $experiment->nd_experiment_id(),
199 type_id
=> $cross_name_cvterm->cvterm_id(),
200 value
=> $cross_name,
203 #store the cross type as an experiment prop
204 $experiment->find_or_create_related('nd_experimentprops' , {
205 nd_experiment_id
=> $experiment->nd_experiment_id(),
206 type_id
=> $cross_type_cvterm->cvterm_id(),
207 value
=> $cross_type,
210 #link the parents to the experiment
211 if ($female_parent) {
212 $experiment->find_or_create_related('nd_experiment_stocks' , {
213 stock_id
=> $female_parent->stock_id(),
214 type_id
=> $female_parent_cvterm->cvterm_id(),
218 $experiment->find_or_create_related('nd_experiment_stocks' , {
219 stock_id
=> $male_parent->stock_id(),
220 type_id
=> $male_parent_cvterm->cvterm_id(),
223 if ($cross_type eq "self" && $female_parent) {
224 $experiment->find_or_create_related('nd_experiment_stocks' , {
225 stock_id
=> $female_parent->stock_id(),
226 type_id
=> $male_parent_cvterm->cvterm_id(),
230 #create a stock of type cross
231 $cross_stock = $chado_schema->resultset("Stock::Stock")->find_or_create(
232 { organism_id
=> $organism_id,
234 uniquename
=> $cross_name,
235 type_id
=> $cross_stock_type_cvterm->cvterm_id,
238 #add stock_id of cross to an array so that the owner can be associated in the phenome schema after the transaction on the chado schema completes
239 push (@added_stock_ids, $cross_stock->stock_id());
242 #link parents to the stock of type cross
243 if ($female_parent) {
245 ->find_or_create_related('stock_relationship_objects', {
246 type_id
=> $female_parent_cvterm->cvterm_id(),
247 object_id
=> $cross_stock->stock_id(),
248 subject_id
=> $female_parent->stock_id(),
249 value
=> $cross_type,
255 ->find_or_create_related('stock_relationship_objects', {
256 type_id
=> $male_parent_cvterm->cvterm_id(),
257 object_id
=> $cross_stock->stock_id(),
258 subject_id
=> $male_parent->stock_id(),
262 if ($cross_type eq "self" && $female_parent) {
264 ->find_or_create_related('stock_relationship_objects', {
265 type_id
=> $male_parent_cvterm->cvterm_id(),
266 object_id
=> $cross_stock->stock_id(),
267 subject_id
=> $female_parent->stock_id(),
272 #link the stock of type cross to the experiment
273 $experiment->find_or_create_related('nd_experiment_stocks' , {
274 stock_id
=> $cross_stock->stock_id(),
275 type_id
=> $progeny_cvterm->cvterm_id(),
277 #link the experiment to the project
278 $experiment->find_or_create_related('nd_experiment_projects', {
279 project_id
=> $project->project_id()
282 #link the cross program to the breeding program
283 my $trial_object = CXGN
::Trial
->new({ bcs_schema
=> $chado_schema, trial_id
=> $project->project_id() });
284 $trial_object->set_breeding_program($program->project_id());
286 #add the cross type to the experiment as an experimentprop
288 ->find_or_create_related('nd_experimentprops' , {
289 nd_experiment_id
=> $experiment->nd_experiment_id(),
290 type_id
=> $cross_type_cvterm->cvterm_id(),
291 value
=> $cross_type,
298 #try to add all crosses in a transaction
300 $chado_schema->txn_do($coderef);
302 $transaction_error = $_;
305 if ($transaction_error) {
306 print STDERR
"Transaction error creating a cross: $transaction_error\n";
310 foreach my $stock_id (@added_stock_ids) {
311 #add the owner for this stock
312 $phenome_schema->resultset("StockOwner")
314 stock_id
=> $stock_id,
315 sp_person_id
=> $owner_sp_person_id,
323 sub validate_crosses
{
325 my $chado_schema = $self->get_chado_schema();
326 my @crosses = @
{$self->get_crosses()};
327 my $invalid_cross_count = 0;
334 $location_lookup = CXGN
::Location
::LocationLookup
->new({ schema
=> $chado_schema, location_name
=> $self->get_location() });
335 $geolocation = $location_lookup->get_geolocation();
338 print STDERR
"Location ".$self->get_location()." not found\n";
342 $program_lookup = CXGN
::BreedersToolbox
::Projects
->new({ schema
=> $chado_schema});
343 $program = $program_lookup->get_breeding_program_by_name($self->get_program());
345 print STDERR
"Breeding program ". $self->get_program() ." not found\n";
349 foreach my $cross (@crosses) {
350 my $validated_cross = $self->_validate_cross($cross);
352 if (!$validated_cross) {
353 $invalid_cross_count++;
358 if ($invalid_cross_count > 0) {
359 print STDERR
"There were $invalid_cross_count invalid crosses\n";
366 sub _validate_cross
{
368 my $pedigree = shift;
369 my $chado_schema = $self->get_chado_schema();
370 my $name = $pedigree->get_name();
371 my $cross_type = $pedigree->get_cross_type();
372 my $female_parent_name;
373 my $male_parent_name;
377 if ($cross_type eq "biparental") {
378 $female_parent_name = $pedigree->get_female_parent()->get_name();
379 $male_parent_name = $pedigree->get_male_parent()->get_name();
380 $female_parent = $self->_get_accession($female_parent_name);
381 $male_parent = $self->_get_accession($male_parent_name);
383 if (!$female_parent || !$male_parent) {
384 print STDERR
"Parent $female_parent_name or $male_parent_name in pedigree is not a stock\n";
388 } elsif ($cross_type eq "self") {
389 $female_parent_name = $pedigree->get_female_parent()->get_name();
390 $female_parent = $self->_get_accession($female_parent_name);
392 if (!$female_parent) {
393 print STDERR
"Parent $female_parent_name in pedigree is not a stock\n";
397 } elsif ($cross_type eq "open") {
398 $female_parent_name = $pedigree->get_female_parent()->get_name();
399 $female_parent = $self->_get_accession($female_parent_name);
401 if (!$female_parent) {
402 print STDERR
"Parent $female_parent_name in pedigree is not a stock\n";
406 #add support for other cross types here
417 my $accession_name = shift;
418 my $chado_schema = $self->get_chado_schema();
419 my $stock_lookup = CXGN
::Stock
::StockLookup
->new(schema
=> $chado_schema);
421 my $accession_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'accession', 'stock_type');
422 my $population_cvterm = SGN
::Model
::Cvterm
->get_cvterm_row($chado_schema, 'population', 'stock_type');
424 $stock_lookup->set_stock_name($accession_name);
425 $stock = $stock_lookup->get_stock_exact();
428 print STDERR
"Name in pedigree is not a stock\n";
432 if (($stock->type_id() != $accession_cvterm->cvterm_id()) && ($stock->type_id() != $population_cvterm->cvterm_id()) ) {
433 print STDERR
"Name in pedigree is not a stock of type accession or population\n";