I create an openlayers map application for creating histogram from COG layer. I using WebGLTile layer and DataTile source. In a map I have only 2 colors but gl.readPixels returns 12 color values.
map screenshot
part of code:
map.on("click", (evt) => {
var buffer = {};
const gl = webgl.getRenderer().helper.getGL();
const pixelData = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);
let r, g, b, c = 0;
for (let i = 0; i < pixelData.length; i+=4) {
r = pixelData[i];
g = pixelData[i+1];
b = pixelData[i+2];
let item;
item = [r, g, b].reduce((acc, cur) => {
if (!acc.hasOwnProperty(cur)) {
acc[cur] = {};
}
return acc[cur];
}, buffer);
item.count = (item.count || 0) + 1;
}
});
In final buffer I need only
{
"165": {
"1": {
"38": {
"count": 1181613
}
},
},
"255": {
"255": {
"191": {
"count": 351
}
}
}
}
but I get 12 colors between these two intervals.
{
"165": {
"1": {
"38": {
"count": 1181613
}
},
"2": {
"39": {
"count": 130473
}
}
},
"168": {
"10": {
"43": {
"count": 130413
}
}
},
"169": {
"11": {
"44": {
"count": 15151
}
}
},
"174": {
"27": {
"54": {
"count": 130481
}
},
"28": {
"54": {
"count": 14792
}
}
},
"177": {
"36": {
"59": {
"count": 14460
}
}
},
"178": {
"37": {
"59": {
"count": 1631
}
}
},
"242": {
"219": {
"170": {
"count": 130366
}
}
},
"243": {
"220": {
"170": {
"count": 14487
}
}
},
"246": {
"228": {
"175": {
"count": 14884
}
},
"229": {
"175": {
"count": 1574
}
}
},
"251": {
"245": {
"185": {
"count": 15250
}
}
},
"252": {
"246": {
"186": {
"count": 1586
}
}
},
"255": {
"254": {
"190": {
"count": 1528
}
},
"255": {
"191": {
"count": 351
}
}
}
}
I have no idea why is this happenning and I spent days searching for solution.
I found some example, not with openlayers, and this approach was fine. returns only two values from double-color square.
It's some kind of interpolation on the openlayers side?
Thnaks for any help!
Related
Summary
I am developing my own rate-limiting plugins based on the official one.
The origin schema looks like:
fields = {
{ config = {
type = "record",
fields = {
{ second = { type = "number", gt = 0 }, },
{ minute = { type = "number", gt = 0 }, },
}
...
},
},
My schema looks like:
{ config = {
type = "record",
fields = {
{ plans = {
type = "array",
elements = {
type = "record",
fields = {
{ second = { type = "number", gt = 0 }, },
{ minute = { type = "number", gt = 0 }, },
}
},
},},
},
custom_validator = validate_periods_order,
},
},
You can see that the first field is called "plans" and it's type is an array which means I will have config.plans[0].second, config.plans[0].second, ... and the original one was config.second
Below is the origin entity_checks function of rate-limiting, I have no idea how to re-write it to match my schema since it changed from simple record type to array type
entity_checks = {
{ at_least_one_of = { "config.second", "config.minute", "config.hour", "config.day", "config.month", "config.year" } },
{ conditional = {
if_field = "config.policy", if_match = { eq = "config.redis" },
then_field = "config.redis_host", then_match = { required = true },
} },
{ conditional = {
if_field = "config.policy", if_match = { eq = "config.redis" },
then_field = "config.redis_port", then_match = { required = true },
} },
{ conditional = {
if_field = "config.policy", if_match = { eq = "config.redis" },
then_field = "config.redis_timeout", then_match = { required = true },
} },
},
Create a local schema for plan
local plan_schema = {
type = "record",
fields = {
{ second = { type = "number", gt = 0 }, },
{ minute = { type = "number", gt = 0 }, },
},
custom_validator = validate_periods_order,
entity_checks = {
{ at_least_one_of = { "second", "minute" } },
}
}
Then on your config set plans as an array of plan
return {
name = plugin_name,
fields = {
{ consumer = typedefs.no_consumer },
{ protocols = typedefs.protocols_http },
{ config = {
type = "record",
fields = {
{ plans = {
type = "array",
elements = plan_schema ,
} },
} },
},
}
it's been a long time I don't use Swift.
I have a response data like this and I saved it into an array named responseData:
[
{
"type": "Switch",
"name": "Switch1",
"search_key": "is_promotion",
"key": "is_promotion=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch2",
"search_key": "shop_type",
"key": "shop_type=2",
"icon": ""
},
{
"type": "Switch",
"name": "Switch3",
"search_key": "is_certified",
"key": "is_certified=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch4",
"search_key": "shop_free_shipping",
"key": "shop_free_shipping=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch5",
"search_key": "is_loyalty",
"key": "is_loyalty=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch6",
"search_key": "is_using_instant",
"key": "is_using_instant=1",
"icon": ""
},
{
"type": "Switch",
"name": "Switch7",
"search_key": "is_installment",
"key": "is_installment=1",
"icon": ""
},
{
"type": "Range",
"name": "Price Range",
"search_key": "level_Price_Max_Min",
"value": [
{
"option_id": 0,
"option_name": 0
},
{
"option_id": 0,
"option_name": 10000000
}
]
},
{
"type": "ColorTerm",
"name": "Color",
"search_key": "color_key",
"value": [
{
"option_id": 605,
"value": "Black",
"color_id": 13,
"image": "",
"option_name": "Black",
"background": "#000000",
"option_active": "",
"facet_count": 52655
},
Now I wanna group all dictionary with type Switch into one array and I can access to the keys inside it, then present data of both Switch type array and the others type on a UITableView which have 2 section (Switch type in section 0). How can I do it? I have to search some other solution but I don't understand how to apply them to my code for work.
Here is my FilterModel class:
class FilterModel: NSObject, NSCoding, NSCopying {
override func copy(with zone: NSZone? = nil) -> Any {
// This is the reason why `init(_ model: GameModel)`
// must be required, because `GameModel` is not `final`.
let copy = FilterModel(dict: self.dictionary)
if let arrAttribute = NSArray(array: self.value , copyItems: true) as? [AttributeValueModel] {
copy.value = arrAttribute
}
return copy
}
override init(dict: Dictionary<String, Any>) {
super.init(dict: dict);
value = self.valueParse()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
var name: String? {
return self.dictionary.getString(forKey: "name")
}
var icon: String? {
return self.dictionary.getString(forKey: "icon")
}
var search_key: String? {
return self.dictionary.getString(forKey: "search_key")
}
var key: String? {
return self.dictionary.getString(forKey: "key")
}
var type: FilterDisplayType {
let type = self.dictionary.getString(forKey: "type")
return self.getType(string: type)
}
var value: [AttributeValueModel] = [];
func valueParse()-> [AttributeValueModel] {
// with switch type, Just set true or false
// Change ParentValue to Child
if type == .Switch {
let dict:Dictionary<String, AnyObject> = [
"option_id": "false" as AnyObject,
"option_name": self.name! as AnyObject,
"name": self.name! as AnyObject,
"icon": self.icon! as AnyObject
]
let item = AttributeValueModel(dict:dict);
return [item]
}
guard let childs = (self.dictionary["value"]) as? [Dictionary<String, AnyObject>]
else { return [] }
var output: [AttributeValueModel] = [];
for aDict in childs {
let item = AttributeValueModel(dict:aDict);
if type == .Range && item.option_id == "0" {
item.setRangeOptionID(aValue: item.option_name!)
}
output.append(item);
}
return output;
}
///get list AttributeValueModel Selected
func selectedValues() -> [AttributeValueModel] {
var output: [AttributeValueModel] = [];
for itemTemp in self.value {
if(itemTemp.selected){
if type == .Switch {
itemTemp.setSelectedOptionID()
}
output.append(itemTemp);
}
}
return output;
}
/// make a Filter Item from attributeValues Seleted
func getFilterItem() -> FilterItem? {
var itemFilter: FilterItem = FilterItem(key: self.search_key!, value: "")
itemFilter.key = self.search_key!
let output: NSMutableArray = [];
for attItem in self.selectedValues() {
if attItem.option_id != "" {
output.add(attItem.option_id!);
}
}
if(output.count == 0) {
return nil;
}
let valueString = output.componentsJoined(by: ",");
itemFilter.value = valueString;
return itemFilter
}
///get list AttributeValueModel Selected
func resetToDefault() -> [AttributeValueModel] {
var output: [AttributeValueModel] = [];
for itemTemp in self.value {
if(itemTemp.selected){
itemTemp.selected = false
if type == .Switch {
itemTemp.setSelectedOptionID()
}
if type == .Range {
itemTemp.setRangeOptionID(aValue: itemTemp.option_name!)
}
output.append(itemTemp);
}
}
return output;
}
//for UI
var wasExpanding = false
var numberOfRow:Int = 0
/************/
var attributeNameLength: Int {
var string = ""
for item in valueParse() {
string += item.option_name!
}
return string.count
}
var lenghtSizeName:Int {
var row:Int = 1
var width:CGFloat = 0
let padding:CGFloat = 8
let screen = screenWidth - 50 - 16
for item in valueParse() {
let size = ((item.option_name ?? "") as NSString).size(withAttributes: [
NSAttributedStringKey.font : UIFont.fontRegular_Big()
])
let totalWidth = size.width + padding + 16
if totalWidth <= CGFloat(32) {
width += 32
if width >= screen {
row += 1
width = 32
}
} else {
width += totalWidth
if width >= screen {
row += 1
width = totalWidth
}
}
}
return row
}
}
You can filter your response data to get only switches in an array.
responseData.filter {($0.type ?? "") == "Switch"}
And of course != would give you non switches.
I have a type in elasticsearch type_1 in which it has only two fields name and value.
I have following elasticsearch query, Is there any alternative of below query that produce same result using only one has_child ?
GET /my_index/my_type/_search
{
"query": {
"bool": {
"must": [
{
"has_child": {
"type": "type_1",
"query": {
"bool": {
"must": [
{
"term": {
"name": "field_1"
}
},
{
"term": {
"value": "val1"
}
}
]
}
}
}
},
{
"has_child": {
"type": "type_1",
"query": {
"bool": {
"must": [
{
"term": {
"name": "field_2"
}
},
{
"term": {
"value": "val2"
}
}
]
}
}
}
}
]
}
}
}
I am working with the Searchkick Gem and Elastic search and am trying to understand the aggregations behavior.
I have three facets (Aggregations): City, State and Company.
If I filter by any one of them, the counts of other two are reduced to reflect the total in the result set. But the selected facet comes back with all values. So say I had 100 items in the index, and I filtered by a Company that had 2 total items in the index, the City and State counts are updated to reflect no more than 2. But the Company count remains at 100.
Example (filtered to City=Atlanta)
{
"query": {
"function_score": {
"functions": [
{
"filter": {
"and": [
{
"term": {
"featured": true
}
}
]
},
"boost_factor": 1000
}
],
"query": {
"match_all": {}
},
"score_mode": "sum"
}
},
"size": 20,
"from": 0,
"post_filter": {
"bool": {
"filter": [
{
"range": {
"expiration_date": {
"from": "2016-08-18T23:07:15.670-04:00",
"include_lower": true
}
}
},
{
"range": {
"created_at": {
"to": "2016-08-18T23:07:15.670-04:00",
"include_upper": true
}
}
},
{
"term": {
"published": true
}
},
{
"term": {
"tenant_id": 4
}
},
{
"term": {
"city": "Atlanta"
}
}
]
}
},
"aggs": {
"company": {
"filter": {
"bool": {
"must": [
{
"range": {
"expiration_date": {
"from": "2016-08-18T23:07:15.670-04:00",
"include_lower": true
}
}
},
{
"range": {
"created_at": {
"to": "2016-08-18T23:07:15.670-04:00",
"include_upper": true
}
}
},
{
"term": {
"published": true
}
},
{
"term": {
"tenant_id": 4
}
},
{
"term": {
"city": "Atlanta"
}
}
]
}
},
"aggs": {
"company": {
"terms": {
"field": "company",
"size": 10
}
}
}
},
"city": {
"filter": {
"bool": {
"must": [
{
"range": {
"expiration_date": {
"from": "2016-08-18T23:07:15.670-04:00",
"include_lower": true
}
}
},
{
"range": {
"created_at": {
"to": "2016-08-18T23:07:15.670-04:00",
"include_upper": true
}
}
},
{
"term": {
"published": true
}
},
{
"term": {
"tenant_id": 4
}
}
]
}
},
"aggs": {
"city": {
"terms": {
"field": "city",
"size": 10
}
}
}
},
"state": {
"filter": {
"bool": {
"must": [
{
"range": {
"expiration_date": {
"from": "2016-08-18T23:07:15.670-04:00",
"include_lower": true
}
}
},
{
"range": {
"created_at": {
"to": "2016-08-18T23:07:15.670-04:00",
"include_upper": true
}
}
},
{
"term": {
"published": true
}
},
{
"term": {
"tenant_id": 4
}
},
{
"term": {
"city": "Atlanta"
}
}
]
}
},
"aggs": {
"state": {
"terms": {
"field": "state",
"size": 10
}
}
}
}
},
"fields": []
}
Result (2 result returned, but 58 City Aggregations come back). Note Company and City return correct # of Aggregations:
{
"took": 114,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "jobs_development_20160818140128648",
"_type": "job",
"_id": "457134",
"_score": 1
},
{
"_index": "jobs_development_20160818140128648",
"_type": "job",
"_id": "457137",
"_score": 1
}
]
},
"aggregations": {
"city": {
"doc_count": 58,
"city": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 19,
"buckets": [
{
"key": "Los Angeles",
"doc_count": 8
},
{
"key": "London",
"doc_count": 7
},
{
"key": "New York",
"doc_count": 7
},
{
"key": "Burbank",
"doc_count": 5
},
{
"key": "Pasig",
"doc_count": 3
},
{
"key": "Atlanta",
"doc_count": 2
},
{
"key": "Chicago",
"doc_count": 2
},
{
"key": "Culver City",
"doc_count": 2
},
{
"key": "London Borough of Hackney",
"doc_count": 2
},
{
"key": "Birmingham",
"doc_count": 1
}
]
}
},
"company": {
"doc_count": 2,
"company": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Second Story",
"doc_count": 2
}
]
}
},
"state": {
"doc_count": 2,
"state": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Georgia",
"doc_count": 2
}
]
}
}
}
}
What am I missing? Is this correct behavior?
I'm very new in Elasticsearch and have a question about the hierarchical tokenizer of a path. Here is my code example:
My mapping code:
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"path-analyzer": {
"type": "custom",
"tokenizer": "path-tokenizer"
}
},
"tokenizer": {
"path-tokenizer": {
"type": "path_hierarchy",
"delimiter": "."
}
}
}
},
"mappings": {
"my_type": {
"dynamic": "strict",
"properties": {
"group_path": {
"type": "string",
"index_analyzer": "path-analyzer",
"search_analyzer": "keyword"
}
}
}
}
}
This is my PUT:
PUT /my_index/my_type/1
{
"group_path": ["Book.Thriller.Adult","DVD.Comedy.Kids"]
}
This is my Query:
GET /my_index/my_type/_search?search_type=count
{
"aggs": {
"category": {
"terms": {
"field": "group_path",
"size": 0
}
}
}
}
And the result:
{
...
"aggregations": {
"category": {
"buckets": [
{
"key": "Book",
"doc_count": 1
},
{
"key": "Book.Thriller",
"doc_count": 1
},
{
"key": "Book.Thriller.Adult",
"doc_count": 1
},
{
"key": "DVD",
"doc_count": 1
},
{
"key": "DVD.Comedy",
"doc_count": 1
},
{
"key": "DVD.Comedy.Kids",
"doc_count": 1
}
]
}
}
}
So far is everything good. What I'm looking for is that how can I create buckets for example only for the first category. How can I get result like that:
{
...
"aggregations": {
"category": {
"buckets": [
{
"key": "Book",
"doc_count": 1
},
{
"key": "DVD",
"doc_count": 1
}
]
}
}
}
Thank you for any help.
The only way I found to do this is to use the exclude syntax to exclude the levels you don't want.
{
"aggs": {
"category": {
"terms": {
"field": "group_path",
"size": 0,
"exclude" : ".*\\..*"
}
}
}
}
Will then return
aggregations: {
category: {
buckets: [
{
key: Book
doc_count: 1
}
{
key: DVD
doc_count: 1
}
]
}
}
If you select book, you can then search like this
{
"query" : {
"filtered": {
"filter": {
"prefix": {
"group_path": "Book"
}
}
}
},
"aggs" : {
"category": {
"terms": {
"field": "group_path",
"size": 0,
"include" : "Book\\..*",
"exclude": ".*\\..*\\..*"
}
}
}
}
Will then return
aggregations: {
category: {
buckets: [
{
key: Book.Thriller
doc_count: 1
}
]
}
}