4 CXGN::Marker::Location;
8 John Binns <zombieite@gmail.com>
12 Location object. It's a very simple match to the marker_location table in the database, but it has a little bit of intelligence too.
16 package CXGN
::Marker
::Location
;
19 use CXGN
::Marker
::Tools
;
20 use CXGN
::DB
::Connection
;
21 use CXGN
::Tools
::Text
;
26 my $location=CXGN::Marker::Location->new($dbh,$location_id);
28 Takes a dbh and a location_id and returns an object representing little more than a row in the marker_location table.
30 my $location=CXGN::Marker::Location->new($dbh);
32 Takes a dbh and returns an empty object which can perform an insert into the marker_location table.
40 unless(CXGN
::DB
::Connection
::is_valid_dbh
($dbh))
44 my $self=bless({},$class);
55 marker_location.map_version_id,
58 confidence_name as confidence,
62 inner join marker_location using (location_id)
63 inner join linkage_group using (lg_id)
64 inner join marker_confidence using (confidence_id)
69 my $hr=$q->fetchrow_hashref();
70 while(my($key,$value)=each %$hr)
80 my $id=$location->location_id();
82 Gets location ID. Cannot set it since it is either retrieved from the database or sent in to the constructor.
86 #this is not a setter, since these ids are assigned by the database
90 return $self->{location_id
};
93 =head2 marker_id, lg_name, map_version_id, position, confidence, subscript
105 unless($value=~/^\d+$/)
107 croak
"Marker ID must be a number, not '$value'";
109 unless(CXGN
::Marker
::Tools
::is_valid_marker_id
($self->{dbh
},$value))
111 croak
"Marker ID '$value' does not exist in the database";
113 $self->{marker_id
}=$value;
115 return $self->{marker_id
};
124 unless($self->{map_version_id
})
126 croak
"You must set this object's map_version_id before throwing around lg_names like that, else how can it know what map_version those lg_names are on?";
128 my $lg_id=CXGN
::Marker
::Tools
::get_lg_id
($self->{dbh
},$lg_name,$self->{map_version_id
});
131 croak
"Linkage group '$lg_name' does not exist on map_version_id '$self->{map_version_id}'";
133 $self->{lg_id
}=$lg_id;
134 $self->{lg_name
}=$lg_name;
136 return $self->{lg_name
};
144 unless ($self->{map_version_id
}) {
145 croak
"You must set map_version_id before trying to set lg_id. Thanks!\n";
147 $self->{lg_id
}=$lg_id;
149 return $self->{lg_id
};
155 my($map_version_id)=@_;
158 unless($map_version_id=~/^\d+$/)
160 croak
"Map version ID must be an integer, not '$map_version_id'";
162 $self->{map_version_id
}=$map_version_id;
164 return $self->{map_version_id
};
172 if ($self->{position
} =~ /\-/) { # if position describes a range, such as a QTL
173 print STDERR
"RANGE DETECTED ($self->{position})\n";
174 ($self->{position_north
}, $self->{position_south
}) = split "-", $self->{position
};
175 $self->{position
} = ($self->{position_south
} - $self->{position_north
})/2;
180 if(defined($position))
182 unless(CXGN
::Tools
::Text
::is_number
($position))
184 print STDERR
"Position must be a floating-point number, not '$position'";
186 $self->{position
}=$position;
188 return $self->{position
};
198 $confidence_id=CXGN
::Marker
::Tools
::get_marker_confidence_id
($self->{dbh
},$confidence);
199 unless(defined($confidence_id))
201 croak
"Confidence ID not found for confidence '$confidence'";
203 $self->{confidence_id
}=$confidence_id;
204 $self->{confidence
}=$confidence;
206 return $self->{confidence
};
215 $subscript=uc($subscript);
216 unless($subscript=~/^[ABC]$/)
218 croak
"Subscript must be a 'A', 'B', or 'C', not '$subscript'";
220 $self->{subscript
}=$subscript;
222 return $self->{subscript
};
227 if($location1->equals($location2)){print"Location 1 and 2 are the same.";}
229 Takes another location object and tells you if it is equivalent to the first location object.
239 $self->{marker_id
}==$other->{marker_id
}
240 and $self->{lg_id
}==$other->{lg_id
}
241 and $self->{map_version_id
}==$other->{map_version_id
}
242 and $self->{position
}==$other->{position
}
243 and $self->{confidence
} eq $other->{confidence
}
244 and $self->{subscript
} eq $other->{subscript
}
254 if($location->exists()){print"Location exists in database.";}
256 Returns its location_id if location is already in the database, or undef if not. Mainly used by store_unless_exists.
263 unless($self->{marker_id
})
265 croak
"Cannot test for a location's existence without knowing which marker it goes with--store marker and set experiment's marker ID before storing locations";
267 unless($self->{lg_id
})
269 croak
"You really should have an lg_id set before testing for a location's existence";
271 unless($self->{map_version_id
})
273 croak
"You really should have a map_version_id set before testing for a location's existence";
275 unless(defined($self->{position
}))
277 croak
"You really should have a position set before testing for a location's existence";
279 unless(defined($self->{confidence_id
}))
281 croak
"You really should have a confidence_id set before testing for a location's existence";
283 if($self->{location_id
})
285 #warn"I think it's pretty obvious that this location exists, since it seems to have been loaded from the database, or recently stored to the database--it already has an id of $self->{location_id}";
286 return $self->{location_id
};
288 my $dbh=$self->{dbh
};
296 inner join marker_experiment using (location_id)
300 and marker_location.map_version_id=?
303 and not(subscript is distinct from ?)
305 $q->execute($self->{marker_id
},$self->{lg_id
},$self->{map_version_id
},$self->{position
},$self->{confidence_id
},$self->{subscript
});
306 my %found_location_ids;#a place to keep all location IDs that match for this marker, for use in error checking in a moment
307 my($location_id)=$q->fetchrow_array();
308 if($location_id)#if we found some matching locations for this marker
310 $self->{location_id
}=$location_id;#get the ID of the existing row in the database so we know we've already been stored
311 $found_location_ids{$location_id}=1;#make a note of the location ID found
312 while(my($other_location_id)=$q->fetchrow_array())#grab all other location IDs
314 $found_location_ids{$other_location_id}=1;
316 if(keys(%found_location_ids)>1)#if we found more than one matching location ID, then the database data is not how we expect it to be
318 die"Multiple locations found like\n".$self->as_string()."Locations found: ".CXGN
::Tools
::Text
::list_to_string
(keys(%found_location_ids));
320 return $self->{location_id
};
325 =head2 exists_with_any_confidence
327 Checks to see if a location exists, but not knowing its confidence. Used by CAPS loading scripts which know which location
328 the PCR experiment maps to, but they do not know the confidence.
330 $loc->exists_with_any_confidence() or die"Could not find location:\n".$loc->as_string()."in database--load locations first, before running this script";
334 sub exists_with_any_confidence
337 unless($self->{marker_id
})
339 croak
"Cannot test for a location's existence without knowing which marker it goes with--store marker and set experiment's marker ID before storing locations";
341 unless($self->{lg_id
})
343 croak
"You really should have an lg_id set before testing for a location's existence";
345 unless($self->{map_version_id
})
347 croak
"You really should have a map_version_id set before testing for a location's existence";
349 unless(defined($self->{position
}))
351 croak
"You really should have a position set before testing for a location's existence";
353 if(defined($self->{confidence_id
}))
355 croak
"You have a confidence_id set--why not just use the 'exists' function instead?";
357 if($self->{location_id
})
359 #warn"I think it's pretty obvious that this location exists, since it seems to have been loaded from the database, or recently stored to the database--it already has an id of $self->{location_id}";
360 return $self->{location_id
};
362 my $dbh=$self->{dbh
};
370 inner join marker_experiment using (location_id)
376 and not(subscript is distinct from ?)
378 $q->execute($self->{marker_id
},$self->{lg_id
},$self->{map_version_id
},$self->{position
},$self->{subscript
});
379 my %found_location_ids;#a place to keep all location IDs that match for this marker, for use in error checking in a moment
380 my($location_id)=$q->fetchrow_array();
381 if($location_id)#if we found some matching locations for this marker
383 $self->{location_id
}=$location_id;#get the ID of the existing row in the database so we know we've already been stored
384 $found_location_ids{$location_id}=1;#make a note of the location ID found
385 while(my($other_location_id)=$q->fetchrow_array())#grab all other location IDs
387 $found_location_ids{$other_location_id}=1;
389 if(keys(%found_location_ids)>1)#if we found more than one matching location ID, then the database data is not how we expect it to be
391 die"Multiple locations found like\n".$self->as_string()."Locations found: ".CXGN
::Tools
::Text
::list_to_string
(keys(%found_location_ids));
393 return $self->{location_id
};
398 =head2 store_unless_exists
400 my $location_id,$existing_location_id,$new_location_id;
401 $location_id=$new_location_id=$location->store_unless_exists();
404 $location_id=$existing_location_id=$location->location_id();
407 Makes a database insert unless a similar row exists. Returns a location_id ONLY if a new insert was made. If a matching entry was found, location_id is now set, but not returned.
411 sub store_unless_exists
414 if($self->exists()){return;}
415 unless($self->{lg_id
})
419 unless($self->{map_version_id
})
421 croak
"No map_version_id set";
423 unless(defined($self->{position
}))
425 croak
"No position set";
427 unless(defined($self->{confidence_id
}))
429 croak
"No confidence set";
431 my $dbh=$self->{dbh
};
433 my $statement='insert into sgn.marker_location (lg_id,map_version_id,position,confidence_id,subscript, position_north, position_south) values (?,?,?,?,?,?,?)';
434 my @values=($self->{lg_id
},$self->{map_version_id
},$self->{position
},$self->{confidence_id
},$self->{subscript
}, $self->{position_north
}, $self->{position_south
});
435 my $q=$dbh->prepare($statement);
436 #print STDERR "$statement; (@values)\n";
437 $q->execute(@values);
438 $self->{location_id
}=$dbh->last_insert_id('marker_location') or croak
"Can't find last insert id for location ".$self->as_string();
439 return($self->{location_id
});
444 print $location->as_string();
446 Prints a location string for debugging.
453 my $string="<location>\n";
454 $string.="\tmarker_id: '$self->{marker_id}'\tsubscript: '$self->{subscript}'\n";
455 $string.="\tlg_name: '$self->{lg_name}'\tlg_id: '$self->{lg_id}'\tposition: '$self->{position}'\n";
456 $string.="\tlocation_id: '$self->{location_id}'\tmap_version_id: '$self->{map_version_id}'\n";
457 $string.="\tconfidence: '$self->{confidence}'\tconfidence_id: '$self->{confidence_id}'\n";
458 $string.="</location>\n";