Easily parsable output from rrdtool - rrdtool

I'm working with a large bunch of RRD-files, where I have to query the data quite a lot - and mostly by reading all the data and pass it on.
Currently, I use rrdtool fetch <filename> CF --start XXX --end YYY, but as it only returns data for one CF at a time, I first have to do a separate query to find the CF's (= run and parse rrdtool info <filename>) and then run rrdtool fetch for each found CF. The output is trivial to parse, though.
Alternately, there is rrdtool xport DEF:XX=<filename>:RRA:CF ... XPORT:XX:XX ... with multiple "sets" of the latter commands for each thing I want. On the upside, this can give me all the data in one go, but I still need to have a fairly good idea about what data I want beforehand. Also, it only spits out XML (always a hassle to parse).
I have a feeling I'm missing something very obvious, as it simply can't be such a big hassle to get a list of timestamp → numbers out of a file... Any clues?

While there are patches around for adding JSON-support, there is currently no way around:
Parsing at least two different output formats (rrdtool info's ASCII and then either XML from rrdtool xport or tabular data from rrdtool fetch).
Dumping the entire contents of the file to XML via rrdtool dump and then re-implementing quite a bit of librrd's internals.

I've written a parser that turns the output of rrdtool info /tmp/pb_1_amp.rrd into a nested array. So from:
filename = "/tmp/pb_1_amp.rrd"
rrd_version = "0003"
step = 1800
last_update = 1372685403
header_size = 1208
ds[amp].index = 0
ds[amp].type = "GAUGE"
ds[amp].minimal_heartbeat = 3200
ds[amp].min = 0.0000000000e+00
ds[amp].max = 1.0000000000e+02
ds[amp].last_ds = "5.6"
ds[amp].value = 1.6800000000e+01
ds[amp].unknown_sec = 0
rra[0].cf = "AVERAGE"
rra[0].rows = 576
rra[0].cur_row = 385
rra[0].pdp_per_row = 1
rra[0].xff = 5.0000000000e-01
rra[0].cdp_prep[0].value = NaN
rra[0].cdp_prep[0].unknown_datapoints = 0
rra[1].cf = "AVERAGE"
rra[1].rows = 672
rra[1].cur_row = 159
rra[1].pdp_per_row = 6
rra[1].xff = 5.0000000000e-01
rra[1].cdp_prep[0].value = 1.6999833333e+01
rra[1].cdp_prep[0].unknown_datapoints = 0
rra[2].cf = "AVERAGE"
rra[2].rows = 732
rra[2].cur_row = 639
rra[2].pdp_per_row = 24
rra[2].xff = 5.0000000000e-01
rra[2].cdp_prep[0].value = 1.6999833333e+01
rra[2].cdp_prep[0].unknown_datapoints = 0
rra[3].cf = "AVERAGE"
rra[3].rows = 1460
rra[3].cur_row = 593
rra[3].pdp_per_row = 144
rra[3].xff = 5.0000000000e-01
rra[3].cdp_prep[0].value = 6.6083527778e+02
rra[3].cdp_prep[0].unknown_datapoints = 0
to:
Array
(
[filename] => /tmp/pb_1_amp.rrd
[rrd_version] => 0003
[step] => 1800
[last_update] => 1372685403
[header_size] => 1208
[ds] => Array
(
[amp] => Array
(
[index] => 0
[type] => GAUGE
[minimal_heartbeat] => 3200
[min] => 0.0000000000e+00
[max] => 1.0000000000e+02
[last_ds] => 5.6
[value] => 1.6800000000e+01
[unknown_sec] => 0
)
)
[rra] => Array
(
[0] => Array
(
[cf] => AVERAGE
[rows] => 576
[cur_row] => 385
[pdp_per_row] => 1
[xff] => 5.0000000000e-01
[cdp_prep] => Array
(
[0] => Array
(
[value] => NaN
[unknown_datapoints] => 0
)
)
)
[1] => Array
(
[cf] => AVERAGE
[rows] => 672
[cur_row] => 159
[pdp_per_row] => 6
[xff] => 5.0000000000e-01
[cdp_prep] => Array
(
[0] => Array
(
[value] => 1.6999833333e+01
[unknown_datapoints] => 0
)
)
)
[2] => Array
(
[cf] => AVERAGE
[rows] => 732
[cur_row] => 639
[pdp_per_row] => 24
[xff] => 5.0000000000e-01
[cdp_prep] => Array
(
[0] => Array
(
[value] => 1.6999833333e+01
[unknown_datapoints] => 0
)
)
)
[3] => Array
(
[cf] => AVERAGE
[rows] => 1460
[cur_row] => 593
[pdp_per_row] => 144
[xff] => 5.0000000000e-01
[cdp_prep] => Array
(
[0] => Array
(
[value] => 6.6083527778e+02
[unknown_datapoints] => 0
)
)
)
)
)
It's in PHP but it should be easy to port to any other language. Here's the code:
$store = array();
foreach ($lines as $line) {
list($raw_key, $raw_val) = explode(' = ', $line);
$keys = preg_split('/[\.\[\]]/', $raw_key, -1, PREG_SPLIT_NO_EMPTY);
$key_count = count($keys);
$pointer = &$store;
foreach ($keys as $key_num => $key) {
if (!array_key_exists($key, $pointer)) {
$pointer[$key] = array();
}
$pointer = &$pointer[$key];
if ($key_num+1 === $key_count) {
$pointer = trim($raw_val, '"');
}
}
}
It assumes the rrdtool info output is split by newline (\n) and found in $lines. Hope this helps.

If you want the 'table of contents' use rrdtool info, if you want the whole content, use rrdtool dump.
BUT ... why would you want that?
cheers
tobi

Related

Changing cart data during Ajax woocommerce

I'm trying to replace the current WooCommerce cart with a saved one, during Ajax.
This is the code i'm using:
function restore()
{
$current_user_id = get_current_user_id();
if ($current_user_id > 0) {
if (function_exists('get_user_attribute')) {
$buy_now_persistent_cart = get_user_meta($current_user_id, '_buy_now_persistent_cart', true);
error_log(print_r($buy_now_persistent_cart, 1));
if (!empty($buy_now_persistent_cart['cart'])) {
WC()->session->cart = $buy_now_persistent_cart['cart'];
WC()->session->applied_coupons = $buy_now_persistent_cart['applied_coupons'];
if (function_exists('delete_user_attribute')) {
//delete_user_attribute( $current_user_id, '_buy_now_persistent_cart' );
}
//delete_user_meta( $current_user_id, '_buy_now_persistent_cart' );
}
}
}
This is the $buy_now_persistent_cart output:
Array
(
[cart] => Array
(
[3430dcf4efe8aa0c418434656773a73a] => Array
(
[key] => 3430dcf4efe8aa0c418434656773a73a
[product_id] => 126096
[variation_id] => 0
[variation] => Array
(
)
[quantity] => 1
[data_hash] => b5c1d5ca8bae6d4896cf1807cdf763f0
[line_tax_data] => Array
(
[subtotal] => Array
(
)
[total] => Array
(
)
)
[line_subtotal] => 2.4
[line_subtotal_tax] => 0
[line_total] => 2.4
[line_tax] => 0
)
)
[applied_coupons] => Array
(
)
)
When I output WC()->session->cart after setting the new data it seems to have changed correctly, but the updated cart is not there when the Ajax finishes.
I guess it is about saving the cart and/or setting a cart hash and cookies?
I just can't figure it out.
Any help will be appreciated.
I would approach it in a different way. First empty the user cart, then add all the products.
Something like:
if (!empty($buy_now_persistent_cart['cart'])) {
WC()->cart->empty_cart();
foreach($buy_now_persistent_cart['cart'] as $item){
WC()->cart->add_to_cart($item['product_id'], $item['quantity']);
}
}
I didn't tested it, but in general I think it's a better approach than forcing a session

Cakephp sum() with multiplication

Is it possible to find the cakephp with additional condition or can we multiply the sum() field with conditional variable?
I don't know, what could be a best question to let you guys know what I'm asking. so I'm giving a more detail about question. I'm able to find similar data with single array with some trick. but I'm unable to find for this. Please help me or give me an idea to do such task. Thanks.
Using CakePhp 2.6
I want to find data from first table here..
$incentiveweekly=$this->Incentive->find('all',
array('conditions' =>
array(
"AND"=>array(
"Incentive.fromdate >=" => $from,
"Incentive.todate <=" => $to
)
)
)
);
according to number of rows. I have to find another table
Here is the result of above find condition.
Array
(
[Incentive] => Array
(
[id] => 2
[target1] => 3000
[price1] => 1.5
[target2] => 6000
[price2] => 2.5
[target3] => 8000
[price3] => 3.5
[formonth] =>
[type] => 1
[fromdate] => 2016-11-13
[todate] => 2016-11-21
[updatedby] => 1
[created] => 2016-11-15 23:57:21
[modified] => 2016-11-15 23:57:21
)
)
Array
(
[Incentive] => Array
(
[id] => 3
[target1] => 3000
[price1] => 1.5
[target2] => 6000
[price2] => 2.5
[target3] => 8000
[price3] => 3.5
[formonth] =>
[type] => 1
[fromdate] => 2016-11-24
[todate] => 2016-11-28
[updatedby] => 1
[created] => 2016-11-15 23:57:21
[modified] => 2016-11-15 23:57:21
)
)
Now I want to find the array according to number of array record.
$byweek=array(); // Storing Customer data by Target dates in array()
foreach ($incentiveweekly as $weekly){
print_r($weekly);
$target3=$weekly['Incentive']['target3'];
$target2=$weekly['Incentive']['target2'];
$target1=$weekly['Incentive']['target1'];
$price3=$weekly['Incentive']['price3'];
$price2=$weekly['Incentive']['price2'];
$price1=$weekly['Incentive']['price1'];
$byweek[]=$customers=$this->Customer->find('all',array(
'fields'=>array(
'SUM(amount) AS amount',
'created_by'
),
'group' => 'Customer.created_by',
'conditions' => array(
"AND" =>array(
"Customer.created >=" => $weekly['Incentive']['fromdate'],
"Customer.created <=" => $weekly['Incentive']['todate']
)
),
'recursive'=>-1 )
);
//print_r($byweek);
}
I'm getting result like ...
Array
(
[0] => Array
(
[0] => Array
(
[Customer] => Array
(
[created_by] => 3
)
)
)
)
Array
(
[0] => Array
(
[0] => Array
(
[Customer] => Array
(
[created_by] => 3
)
)
)
[1] => Array
(
[0] => Array
(
[Customer] => Array
(
[created_by] => 1
)
)
[1] => Array
(
[Customer] => Array
(
[created_by] => 2
)
)
)
)
But I want that amount would multiply with on the if else condition where I'm using ternary operator.
$value[0]['amount']>=$valuem['Incentive']['target3']?"Target Third":($value[0]['amount']>=$valuem['Incentive']['target2']?"Target Second":($value[0]['amount']>=$valuem['Incentive']['target1']?"Target First":"None"))
Main purpose to find the details are. I want to create an incentive amount where total sales amount should be match with given target amount. If target1 amount one match then incentive would be total amount*price1 and same with target2 and target3. where i'm using tenantry operator. Target price should be multiply(by condition) with the same find condition data.
I search on google and stack overflow but can't find it's solutions. However I'm thankful to stack overflow and all you gusy that i'm able to find a lots of trick and solutions.
I haven't got exactly though you can try with below solution as per my thought,
You need to use WHEN close in MYSQL,
$incenve = 'CASE WHEN amount>5000 THEN "FIRST Target" WHEN amount>3000 THEN "Second Target" ELSE 0 '
and inside fields in above query
'incentive' => $incentive
Thanks Oldskool for this solution Virtualfields with If Condition
Finaly I, Got my solutions by this code bellow. I'm getting result as expected. :)
$this->Customer->virtualFields=array(
'incentive' => "if(SUM(Customer.amount)>=$target3,(SUM(Customer.amount))*$price3,if(SUM(Customer.amount)>=$target2,(SUM(Customer.amount))*$price2,if(SUM(Customer.amount)>=$target1,(SUM(Customer.amount))*$price1,0)))",
);
Now I can use Virtualfied to get the Incentive value.

Regex Using dynamic named subpattern?

I am doing something like this to prepare a dynamic regex.
$mapping = "asa/user/{u}/d/{d}/{f}"; //line 1
$mapper = preg_replace('/\{.*?\}/m','(\w+)',str_replace('/','#',$mapping)); //line 2
preg_match("/".$mapper."/",str_replace('/','#',$input),$arr);
print_r($arr);
which give output like this for $input = /asa/user/ZZA/d/asasa/gh
Array ( [0] => asa#user#ZZA#d#asasa#gh [1] => ZZA [2] => asasa [3] => gh )
What I want is to get something like this.
Array ( [u] => ZZA [d] => asasa [f] => gh )
I know I can do this with using ?P, so trying this
$mapper = preg_replace('/\{.*?\}/m','(?P<name>\w+)',str_replace('/','#',$mapping));
Which obviously would not work as it will use same index name for all params,what i need to do is replace name with u,d,f dynamically.
i can do this with explode i believe, then traversing the array and replace one by one. But is there any better solution to do this type of operation?
At line 2 can read value between braces and then use it as index to replace with?
At line 2 can read value between braces and then use it as index to
replace with?
Yes, by capturing groups () and backrefrences $n.
You should change the second line to:
$mapper = preg_replace('/\{(.*?)\}/m','(?P<$1>\w+)', str_replace('/','#',$mapping));
Which results in:
Array
(
[0] => asa#user#ZZA#d#asasa#gh
[u] => ZZA
[1] => ZZA
[d] => asasa
[2] => asasa
[f] => gh
[3] => gh
)

BIOPERL. Bio::Graphics with GFF file

I need to obtain something like this:
However, I cannot know how to continue... now I have this:
In other words... I cannot know how to add tags and the corresponding transcripts, CDS, etc.
My code right now is the following one:
#!/usr/bin/perl
#use strict;
use Bio::Graphics;
use Bio::SeqFeature::Generic;
my $panel = Bio::Graphics::Panel->new(
-length => 20000,
-width => 800
);
my $full_length = Bio::SeqFeature::Generic->new(
-start => 1,
-end => 20000,
);
$panel->add_track($full_length,
-key => "hola",
-glyph => 'arrow',
-tick => 2,
-fgcolor => 'black',
-double => 1,
);
my $track = $panel->add_track(
-glyph => 'generic',
-label => 1
);
my $track = $panel->add_track(
-glyph => 'generic',
-label => 1
);
$seq = "";
$seqlength = length($seq);
$count = 0;
while (<>) {
chomp;
next if /^\#/;
my #gff_data = split /\t+/;
next if ($gff_data[2] ne "gene");
my $feature = Bio::SeqFeature::Generic->new(
-display_name => $gff_data[8],
-score => $gff_data[5],
-start => $gff_data[3],
-end => $gff_data[4],
);
$track->add_feature($feature);
}
print $panel->png;
I've read as well the CPAN information but no clue... There is a lot of information for NCBI files but nothing for GFF...
My data:
313-9640000-9660000:19634:fwd maker gene 1978 7195 . + . ID=maker-313-9640000-9660000%3A19634%3Afwd-augustus-gene-0.10;Name=maker-313-9640000-9660000%253A19634%253Afwd-augustus-gene-0.10
313-9640000-9660000:19634:fwd maker mRNA 1978 7195 . + . ID=maker-313-9640000-9660000%3A19634%3Afwd-augustus-gene-0.10-mRNA-1;Name=maker-313-9640000-9660000%253A19634%253Afwd-augustus-gene-0.10-mRNA-1;Parent=maker-313-9640000-9660000%3A19634%3Afwd-augustus-gene-0.10
313-9640000-9660000:19634:fwd maker exon 1978 2207 0.48 + . Parent=maker-313-9640000-9660000%3A19634%3Afwd-augustus-gene-0.10-mRNA-1
313-9640000-9660000:19634:fwd maker exon 3081 3457 0.48 + . Parent=maker-313-9640000-9660000%3A19634%3Afwd-augustus-gene-0.10-mRNA-1
313-9640000-9660000:19634:fwd maker exon 3535 3700 0.48 + . Parent=maker-313-9640000-9660000%3A19634%3Afwd-augustus-gene-0.10-mRNA-1
Any help will be very wellcome.
use Bio::Graphics;
use Bio::Tools::GFF;
use Bio::SeqFeature::Generic;
$gfffile = shift;
my $gff = Bio::Tools::GFF->new(-file => $gfffile, -gff_version => 3);
while($feature = $gff->next_feature()) {
$tag = $feature->primary_tag;
push #{$hash{$tag}}, $feature;
}
$gff->close();
my $panel = Bio::Graphics::Panel->new(
-length => 20000,
-width => 800,
-key_style => 'between',
);
my $full_length = Bio::SeqFeature::Generic->new(
-start => 1,
-end => 20000,
);
$panel->add_track($full_length,
-key => "hola",
-glyph => 'arrow',
-tick => 2,
-fgcolor => 'black',
-double => 1,
);
my #colors = qw(cyan orange blue);
my $idx = 0;
for my $tag (sort keys %hash) {
my $features = $hash{$tag};
$panel->add_track($features,
-glyph => 'generic',
-bgcolor => $colors[$idx++ % #colors],
-fgcolor => 'black',
-font2color => 'red',
-key => "${tag}s",
-bump => +1,
-height => 8,
-label => 1,
-description => 1,
);
}
print $panel->png;
What you are showing in the first screen capture is likely from GBrowse, and the track labels (I think this is what you mean by 'tags') are defined in the configuration file. The feature label can be turned on/off by setting the 'label' and 'label_feat' attributes when you create the object. You will have to manually edit the file if you don't like those long strings set as the ID by MAKER.
You can change the appearance of each feature by choosing a different glyph. For example, you chose the 'generic' glyph, so what you get is a pretty generic looking box which just shows you the location of the feature. For nice looking transcripts, take a look at the 'processed_transcript' and 'decorated_transcript' glyphs.
There are also some problems with your code, such duplication of certain sections, but that may be from doing a copy and paste of the code.
I had the same problem than you. The thing is not very easy to explain. Finally I solved it and mi figure is pretty much similar at yours.
In my case I wanted to connect some encode data in the 5' UTR of several genes. And this encode data should be connected with dashed lines.
So I create a Bio::SeqFeature::Generic object and the information to plot inside are my encode regions, so this encode regions need to be sub_located inside :
my $splitlocation = Bio::Location::Split->new();
foreach $encode_regions ....{
$splitlocation->add_sub_Location(Bio::Location::Simple->new(-start=>$start,-end=>$end,- strand=>$strand,-splittype=>"join"));
}
$exones = new Bio::SeqFeature::Generic(
-primary_tag => 'Encode Regions',
-location=>$splitlocation
);

Array Issue with QueryBuilder Doctrine2

I have a Problem with the Querybuilder,
$qb = $this->_em->createQueryBuilder();
$qb->select('k, l')
-> i got a array such as
Array
(
[0] => Array
(
[id] => 15
-> ok
when i do
$qb->select('k.id, l.title')->add('from', 'Base\Entities\Company k')
i get
Array
(
[0] => Array
(
[id] => 15
[title] =>
)
-> ok
ISSUE:
When id do:
$qb->select('k, l.title')->add('from', 'Base\Entities\Company k')
i get:
Array
(
[0] => Array
(
[0] => Array
(
[id] => 15
i always do $result = $query->getArrayResult(); at the End
how can i remove the array in the array? i only want title as part of the array in k (like above)
I believe it's not really possible to do so, You'll have to iterate over the results to achieve this. You can read more about it in documentation.