Newer
Older
Patrick Meidl
committed
$sth->execute;
my @sp;
while (my @row = $sth->fetchrow_array) {
push @sp, $row[0];
}
$sth->finish;
my $species = join(" ", reverse @sp);
$self->throw("Could not determine species scientific name from database.")
unless $species;
return $species;
}
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
=head2 species
Arg[1] : (optional) String $species - species name to set
Example : my $species = $support->species;
my $url = "http://vega.sanger.ac.uk/$species/";
Description : Getter/setter for species name (Genus_species). If not set, it's
determined from database's meta table
Return type : String - species name
Exceptions : none
Caller : general
=cut
sub species {
my $self = shift;
$self->{'_species'} = shift if (@_);
# get species name from database if not set
unless ($self->{'_species'}) {
$self->{'_species'} = join('_',
split(/ /, $self->get_species_scientific_name));
}
return $self->{'_species'};
}
=head2 sort_chromosomes
Arg[1] : (optional) Hashref $chr_hashref - Hashref with chr_name as keys
Example : my $chr = { '6-COX' => 1, '1' => 1, 'X' => 1 };
my @sorted = $support->sort_chromosomes($chr);
Description : Sorts chromosomes in an intuitive way (numerically, then
alphabetically). If no chromosome hashref is passed, it's
retrieve by calling $self->get_chrlength()
Return type : List - sorted chromosome names
Exceptions : thrown if no hashref is provided
Caller : general
=cut
sub sort_chromosomes {
my ($self, $chr_hashref) = @_;
$chr_hashref = $self->get_chrlength unless ($chr_hashref);
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
throw("You have to pass a hashref of your chromosomes")
unless ($chr_hashref and ref($chr_hashref) eq 'HASH');
return (sort _by_chr_num keys %$chr_hashref);
}
=head2 _by_chr_num
Example : my @sorted = sort _by_chr_num qw(X, 6-COX, 14, 7);
Description : Subroutine to use in sort for sorting chromosomes. Sorts
numerically, then alphabetically
Return type : values to be used by sort
Exceptions : none
Caller : internal ($self->sort_chromosomes)
=cut
sub _by_chr_num {
my @awords = split /-/, $a;
my @bwords = split /-/, $b;
my $anum = $awords[0];
my $bnum = $bwords[0];
if ($anum !~ /^[0-9]*$/) {
if ($bnum !~ /^[0-9]*$/) {
return $anum cmp $bnum;
} else {
return 1;
}
}
if ($bnum !~ /^[0-9]*$/) {
return -1;
}
if ($anum <=> $bnum) {
return $anum <=> $bnum;
} else {
if ($#awords == 0) {
return -1;
} elsif ($#bwords == 0) {
return 1;
} else {
return $awords[1] cmp $bwords[1];
}
}
}
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
=head2 split_chromosomes_by_size
Arg[1] : (optional) Int $cutoff - the cutoff in bp between small and
large chromosomes
Example : my $chr_slices = $support->split_chromosomes_by_size;
foreach my $block_size (keys %{ $chr_slices }) {
print "Chromosomes with blocksize $block_size: ";
print join(", ", map { $_->seq_region_name }
@{ $chr_slices->{$block_size} });
}
Description : Determines block sizes for storing DensityFeatures on
chromosomes, and return slices for each chromosome. The block
size is determined so that you have 150 bins for the smallest
chromosome over 5 Mb in length. For chromosomes smaller than 5
Mb, an additional smaller block size is used to yield 150 bins
for the overall smallest chromosome. This will result in
reasonable resolution for small chromosomes and high
performance for big ones.
Return type : Hashref (key: block size; value: Arrayref of chromosome
Bio::EnsEMBL::Slices)
Exceptions : none
Caller : density scripts
=cut
sub split_chromosomes_by_size {
my $self = shift;
my $cutoff = shift || 5000000;
my $slice_adaptor = $self->dba->get_SliceAdaptor;
my $top_slices;
if ($self->param('chromosomes')) {
foreach my $chr ($self->param('chromosomes')) {
push @{ $top_slices }, $slice_adaptor->fetch_by_region('chromosome', $chr);
}
} else {
$top_slices = $slice_adaptor->fetch_all('chromosome');
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
}
my ($big_chr, $small_chr, $min_big_chr, $min_small_chr);
foreach my $slice (@{ $top_slices }) {
if ($slice->length < $cutoff) {
if (! $min_small_chr or ($min_small_chr > $slice->length)) {
$min_small_chr = $slice->length;
}
# push small chromosomes onto $small_chr
push @{ $small_chr }, $slice;
}
if (! $min_big_chr or ($min_big_chr > $slice->length) && $slice->length > $cutoff) {
$min_big_chr = $slice->length;
}
# push _all_ chromosomes onto $big_chr
push @{ $big_chr }, $slice;
}
my $chr_slices;
$chr_slices->{int($min_big_chr/150)} = $big_chr if $min_big_chr;
$chr_slices->{int($min_small_chr/150)} = $small_chr if $min_small_chr;
return $chr_slices;
}
=head2 log
Arg[1] : String $txt - the text to log
Arg[2] : Int $indent - indentation level for log message
Example : my $log = $support->log_filehandle;
$support->log('Log foo.\n', 1);
Description : Logs a message to the filehandle initialised by calling
$self->log_filehandle(). You can supply an indentation level
to get nice hierarchical log messages.
Return type : true on success
Exceptions : thrown when no filehandle can be obtained
Caller : general
=cut
sub log {
my ($self, $txt, $indent) = @_;
$indent ||= 0;
# strip off leading linebreaks so that indenting doesn't break
$txt =~ s/^(\n*)//;
$txt = $1." "x$indent . $txt;
my $fh = $self->{'_log_filehandle'};
throw("Unable to obtain log filehandle") unless $fh;
print $fh "$txt";
return(1);
}
=head2 log_warning
Arg[1] : String $txt - the warning text to log
Arg[2] : Int $indent - indentation level for log message
Arg[2] : Bool - add a line break before warning if true
Example : my $log = $support->log_filehandle;
$support->log_warning('Log foo.\n', 1);
Description : Logs a message via $self->log and increases the warning counter.
Return type : true on success
Exceptions : none
Caller : general
=cut
sub log_warning {
my ($self, $txt, $indent, $break) = @_;
$txt = "WARNING: " . $txt;
$txt = "\n$txt" if ($break);
$self->log($txt, $indent);
$self->{'_warnings'}++;
return(1);
}
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
=head2 log_error
Arg[1] : String $txt - the error text to log
Arg[2] : Int $indent - indentation level for log message
Example : my $log = $support->log_filehandle;
$support->log_error('Log foo.\n', 1);
Description : Logs a message via $self->log and exits the script.
Return type : none
Exceptions : none
Caller : general
=cut
sub log_error {
my ($self, $txt, $indent) = @_;
$txt = "ERROR: ".$txt;
$self->log($txt, $indent);
$self->log("Exiting.\n");
exit;
}
=head2 log_verbose
Arg[1] : String $txt - the warning text to log
Arg[2] : Int $indent - indentation level for log message
Example : my $log = $support->log_filehandle;
$support->log_verbose('Log this verbose message.\n', 1);
Description : Logs a message via $self->log if --verbose option was used
Return type : TRUE on success, FALSE if not verbose
Exceptions : none
Caller : general
=cut
sub log_verbose {
my ($self, $txt, $indent) = @_;
return(0) unless $self->param('verbose');
$self->log($txt, $indent);
return(1);
}
=head2 log_stamped
Arg[1] : String $txt - the warning text to log
Arg[2] : Int $indent - indentation level for log message
Example : my $log = $support->log_filehandle;
$support->log_stamped('Log this stamped message.\n', 1);
Description : Appends timestamp and memory usage to a message and logs it via
$self->log
Return type : TRUE on success
Exceptions : none
Caller : general
=cut
sub log_stamped {
my ($self, $txt, $indent) = @_;
# append timestamp and memory usage to log text
$txt =~ s/(\n*)$//;
$txt .= " ".$self->date_and_mem.$1;
$self->log($txt, $indent);
return(1);
}
=head2 log_filehandle
Arg[1] : (optional) String $mode - file access mode
Example : my $log = $support->log_filehandle;
# print to the filehandle
print $log 'Lets start logging...\n';
# log via the wrapper $self->log()
$support->log('Another log message.\n');
Description : Returns a filehandle for logging (STDERR by default, logfile if
set from config or commandline). You can use the filehandle
directly to print to, or use the smart wrapper $self->log().
Logging mode (truncate or append) can be set by passing the
mode as an argument to log_filehandle(), or with the
--logappend commandline option (default: truncate)
Return type : Filehandle - the filehandle to log to
Exceptions : thrown if logfile can't be opened
Caller : general
=cut
sub log_filehandle {
my ($self, $mode) = @_;
$mode ||= '>';
$mode = '>>' if ($self->param('logappend'));
my $fh = \*STDERR;
if (my $logfile = $self->param('logfile')) {
Patrick Meidl
committed
if (my $logpath = $self->param('logpath')) {
unless (-e $logpath) {
system("mkdir $logpath") == 0 or
$self->log_error("Can't create log dir $logpath: $!\n");
}
Patrick Meidl
committed
$logfile = "$logpath/$logfile";
}
open($fh, "$mode", $logfile) or throw(
"Unable to open $logfile for writing: $!");
}
$self->{'_log_filehandle'} = $fh;
return $self->{'_log_filehandle'};
}
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
=head2 filehandle
Arg[1] : String $mode - file access mode
Arg[2] : String $file - input or output file
Example : my $fh = $support->filehandle('>>', '/path/to/file');
# print to the filehandle
print $fh 'Your text goes here...\n';
Description : Returns a filehandle (*STDOUT for writing, *STDIN for reading
by default) to print to or read from.
Return type : Filehandle - the filehandle
Exceptions : thrown if file can't be opened
Caller : general
=cut
sub filehandle {
my ($self, $mode, $file) = @_;
$mode ||= ">";
my $fh;
if ($file) {
open($fh, "$mode", $file) or throw(
"Unable to open $file for writing: $!");
} elsif ($mode =~ />/) {
$fh = \*STDOUT;
} elsif ($mode =~ /</) {
$fh = \*STDIN;
}
return $fh;
}
=head2 init_log
Example : $support->init_log;
Description : Opens a filehandle to the logfile and prints some header
information to this file. This includes script name, date, user
running the script and parameters the script will be running
with.
Return type : Filehandle - the log filehandle
Exceptions : none
Caller : general
=cut
sub init_log {
my $self = shift;
# get a log filehandle
my $log = $self->log_filehandle;
# print script name, date, user who is running it
my $hostname = `hostname`;
chomp $hostname;
my $script = "$hostname:$Bin/$Script";
my $user = `whoami`;
chomp $user;
$self->log("Script: $script\nDate: ".$self->date."\nUser: $user\n");
# print parameters the script is running with
$self->log("Parameters:\n\n");
$self->log($self->list_all_params);
# remember start time
$self->{'_start_time'} = time;
return $log;
}
=head2 finish_log
Example : $support->finish_log;
Description : Writes footer information to a logfile. This includes the
number of logged warnings, timestamp and memory footprint.
Return type : TRUE on success
Exceptions : none
Caller : general
=cut
sub finish_log {
my $self = shift;
$self->log("\nAll done. ".$self->warnings." warnings. ");
if ($self->{'_start_time'}) {
$self->log("Runtime ");
my $diff = time - $self->{'_start_time'};
my $sec = $diff % 60;
$diff = ($diff - $sec) / 60;
my $min = $diff % 60;
my $hours = ($diff - $min) / 60;
$self->log("${hours}h ${min}min ${sec}sec ");
}
$self->log($self->date_and_mem."\n\n");
return(1);
}
=head2 date_and_mem
Example : print LOG "Time, memory usage: ".$support->date_and_mem."\n";
Description : Prints a timestamp and the memory usage of your script.
Return type : String - timestamp and memory usage
Exceptions : none
Caller : general
=cut
sub date_and_mem {
my $date = strftime "%Y-%m-%d %T", localtime;
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
chomp $mem;
return "[$date, mem $mem]";
}
=head2 date
Example : print "Date: " . $support->date . "\n";
Description : Prints a nicely formatted timestamp (YYYY-DD-MM hh:mm:ss)
Return type : String - the timestamp
Exceptions : none
Caller : general
=cut
sub date {
return strftime "%Y-%m-%d %T", localtime;
}
=head2 mem
Example : print "Memory usage: " . $support->mem . "\n";
Description : Prints the memory used by your script. Not sure about platform
dependence of this call ...
Return type : String - memory usage
Exceptions : none
Caller : general
=cut
sub mem {
chomp $mem;
return $mem;
}
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
=head2 commify
Arg[1] : Int $num - a number to commify
Example : print "An easy to read number: ".$self->commify(100000000);
# will print 100,000,000
Description : put commas into a number to make it easier to read
Return type : a string representing the commified number
Exceptions : none
Caller : general
Status : stable
=cut
sub commify {
my $self = shift;
my $num = shift;
$num = reverse($num);
$num =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
return scalar reverse $num;
}
=head2 fetch_non_hidden_slices
Arg[1] : B::E::SliceAdaptor
Arg[2] : B::E::AttributeAdaptor
Arg[3] : string $coord_system_name (optional) - 'chromosome' by default
Arg[4] : string $coord_system_version (optional) - 'otter' by default
Example : $chroms = $support->fetch_non_hidden_slice($sa);
Description : retrieve all slices from a loutra database that don't have a hidden attribute
Return type : arrayref
Caller : general
Status : stable
=cut
sub fetch_non_hidden_slices {
my $self = shift;
my $aa = shift or throw("You must supply an attribute adaptor");
my $sa = shift or throw("You must supply a slice adaptor");
my $cs = shift || 'chromosome';
my $cv = shift || 'Otter';
my $visible_chroms;
foreach my $chrom ( @{$sa->fetch_all($cs,$cv)} ) {
my $chrom_name = $chrom->name;
my $attribs = $aa->fetch_all_by_Slice($chrom,'hidden');
if ( scalar(@$attribs) > 1 ) {
$self->log_warning("More than one hidden attribute for chromosome $chrom_name\n");
}
elsif ($attribs->[0]->value == 0) {
push @$visible_chroms, $chrom;
}
elsif ($attribs->[0]->value == 1) {
$self->log_verbose("chromosome $chrom_name is hidden\n");
}
else {
$self->log_warning("No hidden attribute for chromosome $chrom_name\n");
}
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
=head2 get_wanted_chromosomes
Arg[1] : B::E::U::ConversionSupport
Arg[2] : B::E::SliceAdaptor
Arg[3] : B::E::AttributeAdaptor
Arg[4] : string $coord_system_name (optional) - 'chromosome' by default
Arg[5] : string $coord_system_version (optional) - 'otter' by default
Example : @chr_names = &Slice::get_wanted_chromosomes($support,$laa,$lsa);
Description : retrieve names of slices from a lutra database that are ready for dumping to Vega.
Deals with list of names to ignore (ignore_chr = LIST)
Return type : arrayref
Caller : general
Status : stable
=cut
sub get_wanted_chromosomes {
my $self = shift;
my $aa = shift or throw("You must supply an attribute adaptor");
my $sa = shift or throw("You must supply a slice adaptor");
my $cs = shift || 'chromosome';
my $cv = shift || 'Otter';
my $export_mode = $self->param('release_type');
my $release = $self->param('vega_release');
my $names;
my $chroms = $self->fetch_non_hidden_slices($aa,$sa,$cs,$cv);
CHROM:
foreach my $chrom (@$chroms) {
my $attribs = $aa->fetch_all_by_Slice($chrom);
my $vals = $self->get_attrib_values($attribs,'vega_export_mod');
if (scalar(@$vals > 1)) {
$self->log_warning ("Multiple attribs for \'vega_export_mod\', please fix before continuing");
exit;
}
next CHROM if (! grep { $_ eq $export_mode} @$vals);
$vals = $self->get_attrib_values($attribs,'vega_release',$release);
if (scalar(@$vals > 1)) {
$self->log_warning ("Multiple attribs for \'vega_release\' value = $release , please fix before continuing");
exit;
}
next CHROM if (! grep { $_ eq $release} @$vals);
my $name = $chrom->seq_region_name;
if (my @ignored = $self->param('ignore_chr')) {
next CHROM if (grep {$_ eq $name} @ignored);
}
push @{$names}, $name;
}
return $names;
}
=head2 get_attrib_values
Arg[1] : Arrayref of B::E::Attributes
Arg[2] : 'code' to search for
Arg[3] : 'value' to search for (optional)
Example : my $c = $self->get_attrib_values($attribs,'name'));
Description : (i) In the absence of an attribute value argument, examines an arrayref
of B::E::Attributes for a particular attribute type, returning the values
for each attribute of that type. Can therefore be used to test for the
number of attributes of that type.
(ii) In the presence of the optional value argument it returns all
attributes with that value ie can be used to test for the presence of an
attribute with that particular value.
Return type : arrayref of values for that attribute
Caller : general
Status : stable
=cut
sub get_attrib_values {
my $self = shift;
my $attribs = shift;
my $code = shift;
my $value = shift;
if (my @atts = grep {$_->code eq $code } @$attribs) {
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
if ($value) {
if (my @values = grep {$_->value eq $value} @atts) {
foreach (@values) {
push @$r, $_->value;
}
return $r;
}
else {
return [];
}
}
else {
foreach (@atts) {
push @$r, $_->value;
}
return $r;
}
}
else {
return [];
}
}
=head2 fix_attrib_value
Arg[1] : Arrayref of existing B::E::Attributes
Arg[2] : dbID of object
Arg[3] : name of object (just for reporting)
Arg[4] : attrib_type.code
Arg[5] : attrib_type.value
Arg[6] : interactive ? (0 by default)
Arg[7] : table
Example : $support->fix_attrib_value($attribs,$chr_id,$chr_name,'vega_export_mod','N',1);
Description : adds a new attribute to an object, or updates an existing attribute with a new value
Can be run in interactive or non-interactive mode (default)
Caller : general
Status : only ever tested with seq_region_attributes to date
=cut
sub fix_attrib_value {
my $self = shift;
my $attribs = shift;
my $id = shift;
my $name = shift;
my $code = shift;
my $value = shift;
my $interact = shift || 0;
my $table = shift || 'seq_region_attrib';
#transiently set interactive parameter to zero
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
my $int_before;
if (! $interact) {
$int_before = $self->param('interactive');
$self->param('interactive',0);
}
#get any existing value(s) for this attribute
my $existings = $self->get_attrib_values($attribs,$code);
#add a new attribute if there is none...
if (! @$existings ) {
if ($self->user_proceed("Do you want to set $name attrib (code = $code) to value $value ?")) {
my $r = $self->store_new_attribute($id,$code,$value);
#reset interactive parameter
$self->param('interactive',$int_before) if (! $interact);
return $r;
}
}
#...warn and exit if you're trying to update more than one value for the same attribute...
elsif (scalar @$existings > 1) {
$self->log_warning("You shouldn't be trying to update multiple attributes with the same code at once ($name:$code,$value), looks like you have duplicate entries in the (seq_region_)attrib table\n");
exit;
}
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
else {
my $existing = $existings->[0];
if ($existing ne $value) {
if ($self->user_proceed("Do you want to reset $name attrib (code = $code) from $existing to $value ?")) {
my $r = $self->update_attribute($id,$code,$value);
$self->param('interactive',$int_before) if (! $interact);
push @$r, $existing;
return $r;
}
}
#...or make no change
else {
$self->param('interactive',$int_before) if (! $interact);
return [];
}
}
}
=head2 _get_attrib_id
Arg[1] : attrib_type.code
Arg[2] : database handle
Example : $self->_get_attrib_id('name',$dbh)
Description : get attrib_type.attrib_type_id from a attrib_type.code
Return type : attrib_type.attrib_type_id
Caller : internal
Status : stable
=cut
sub _get_attrib_id {
my $self = shift;
my $attrib_code = shift;
my $dbh = shift;
my ($attrib_id) = $dbh->selectrow_array(
qq(select attrib_type_id
from attrib_type
where code = ?),
{},
($attrib_code)
);
if (! $attrib_id) {
$self->log_warning("There is no attrib_type_id for code $attrib_code, please patch the attrib_table\n");
exit;
}
else {
return $attrib_id;
}
}
=head2 store_new_attribute
Arg[1] : seq_region.seq_region_id
Arg[2] : attrib_type.code
Arg[3] : attrib_type.value
ARG[4] : table to update (seq_region_attribute by default)
Example : $support->store_new_attribute(23,name,5);
Description : uses MySQL to store an entry (code and value) in an attribute table
(seq_region_attrib by default)
Return type : array_ref
Caller : general
Status : stable
=cut
sub store_new_attribute {
my $self = shift;
my $sr_id = shift;
my $attrib_code = shift;
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
my $table = shift || 'seq_region_attrib';
#get database handle
my $dbh = $self->get_dbconnection('loutre');
#get attrib_type_id for this particular attribute
my $attrib_id = $self->_get_attrib_id($attrib_code,$dbh);
#store
my $r = $dbh->do(
qq(insert into $table
values (?,?,?)),
{},
($sr_id,$attrib_id,$attrib_value)
);
return ['Stored',$r];
}
=head2 update_attribute
Arg[1] : seq_region.seq_region_id
Arg[2] : attrib_type.code
Arg[3] : attrib_type.value
ARG[4] : table to update (seq_region_attribute by default)
Example : $support->update_attribute(23,name,5);
Description : uses MySQL to update an attribute table (seq_region_attrib by default)
Return type : array_ref
Caller : general
Status : stable
=cut
sub update_attribute {
my $self = shift;
my $sr_id = shift;
my $attrib_code = shift;
my $attrib_value = shift;
my $table = shift || 'seq_region_attrib';
my $dbh = $self->get_dbconnection('loutre');
my $attrib_id = $self->_get_attrib_id($attrib_code,$dbh);
#update
my $r = $dbh->do(
qq(update $table
set value = ?
where seq_region_id = $sr_id
and attrib_type_id = $attrib_id),
{},
($attrib_value)
);
return ['Updated',$r];
}