Why are the colors correct but not the labels in the legend on Dojo StackedColumn - dojo

I have an issue with the Legend on a StackedColumn chart. I have set the following dataSeries and legend elements.
In the code, I have the following for loop to assign all the labels to the values so that they appear in the legend.
v = compositeData.dataSeries;
y = compositeData.legend;
for (i = 0; i < v.length; i++) {
dataSeries = v[i];
r += ' ynchart.addSeries("'+y[i]+'", ['+dataSeries+']);'+#NewLine();
}
When I run the code, I end up with
showing the legend except the order of the labels is not in the order I expected. Element [3] is first, followed by [0], 1 and 2. The color of the elements in the legend are in the correct order but somehow the label is not. I have no code in the script anywhere else that sorts anything. Why is the order of the legend label reordering itself and how do I fix it?

When you specify a parameter in a custom control as "multi-instance" you hand over a java.util.List. The List doesn't guarantee you any delivery sequence and that seems what is happening here. So you are probably better of handing over ONE parameter which you then split(). Of course that leans itself to the potential issue that your label and values get out of sync. So you might want to hand over a complete JSON with all included as parameter. Something like:
{ "values" : { "worldwide" : [10,20,30],
"NA" : [2,10,20],
"Europe" : [4,5,4],
"Japan" : [4,5,6]
}
}
You could consider a function that you hand the names of your fields that returns that string for you.

Related

Google Sheets API (v4) - `AutoResizeDimensions` not working

I've got a system that generates and automatically maintains lots of spreadsheets on a Drive account.
Whenever I add data to the sheet I run a 'format' method to pass over and make sure everything is ok.
This generally does things like:
set the default font and size across the sheet
set up the heading row
freeze rows
In addition, I have the code below to make sure the first two columns (index 0 and 1) in the sheet are autoresizing to fit their contents. when I run it though, this element doesn't seem to make a difference. The font, column freezes etc all work.
Other notes:
I only want those 2 columns to auto-resize
the amount of rows in a sheet can vary
this job is appended to the end of several in requestList
My code:
requestList.Requests.Add(new Google.Apis.Sheets.v4.Data.Request()
{
AutoResizeDimensions = new AutoResizeDimensionsRequest()
{
Dimensions = new DimensionRange()
{
SheetId = Convert.ToInt32(sheetId),
Dimension = "COLUMNS",
StartIndex = 0,
EndIndex = 1
}
}
});
var updateRequest = sheetService.Spreadsheets.BatchUpdate(requestList, spreadSheetId);
var updateResponse = updateRequest.Execute();
Could the order which I request the 'format' changes be affecting things maybe? Can anyone help?
As written in the documentation,
the start index is inclusive and the end index is exclusive.
So, For the first two columns, it should be
startIndex = 0,
endIndex = 2

Make line chart with values and dates

In my app i use ios-charts library (swift alternative of MPAndroidChart).
All i need is to display line chart with dates and values.
Right now i use this function to display chart
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let lineChartDataSet = LineChartDataSet(yVals: dataEntries, label: "Items count")
let lineChartData = LineChartData(xVals: dataPoints, dataSet: lineChartDataSet)
dateChartView.data = lineChartData
}
And this is my data:
xItems = ["27.05", "03.06", "17.07", "19.09", "20.09"] //String
let unitsSold = [25.0, 30.0, 45.0, 60.0, 20.0] //Double
But as you can see - xItems are dates in "dd.mm" format. As they are strings they have same paddings between each other. I want them to be more accurate with real dates. For example 19.09 and 20.09 should be very close. I know that i should match each day with some number in order to accomplish it. But i don't know what to do next - how i can adjust x labels margins?
UPDATE
After small research where i found out that many developers had asked about this feature but nothing happened - for my case i found very interesting alternative to this library in Swift - PNChart. It is easy to use, it solves my problem.
The easiest solution will be to loop through your data and add a ChartDataEntry with a value of 0 and a corresponding label for each missing date.
In response to the question in the comments here is a screenshot from one of my applications where I am filling in date gaps with 0 values:
In my case I wanted the 0 values rather than an averaged line from data point to data point as it clearly indicates there is no data on the days skipped (8/11 for instance).
From #Philipp Jahoda's comments it sounds like you could skip the 0 value entries and just index the data you have to the correct labels.
I modified the MPAndroidChart example program to skip a few data points and this is the result:
As #Philipp Jahoda mentioned in the comments the chart handles missing Entry by just connecting to the next data point. From the code below you can see that I am generating x values (labels) for the entire data set but skipping y values (data points) for index 11 - 29 which is what you want. The only thing remaining would be to handle the x labels as it sounds like you don't want 15, 20, and 25 in my example to show up.
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < count; i++) {
xVals.add((i) + "");
}
ArrayList<Entry> yVals = new ArrayList<Entry>();
for (int i = 0; i < count; i++) {
if (i > 10 && i < 30) {
continue;
}
float mult = (range + 1);
float val = (float) (Math.random() * mult) + 3;// + (float)
// ((mult *
// 0.1) / 10);
yVals.add(new Entry(val, i));
}
What I did is fully feed the dates for x data even no y data for it, and just not add the data entry for the specific xIndex, then it will not draw the y value for the xIndex to achieve what you want, this is the easiest way since you just write a for loop and continue if you detect no y value there.
I don't suggest use 0 or nan, since if it is a line chart, it will connect the 0 data or bad things will happen for nan. You might want to break the lines, but again ios-charts does not support it yet (I also asked a feature for this), you need to write your own code to break the line, or you can live with connecting the 0 data or just connect to the next valid data.
The down side is it may has performance drop since many xIndex there, but I tried ~1000 and it is acceptable. I already asked for such feature a long time ago, but it took lot of time to think about it.
Here's a function I wrote based on Wingzero's answer (I pass NaNs for the entries in the values array that are empty) :
func populateLineChartView(lineChartView: LineChartView, labels: [String], values: [Float]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<labels.count {
if !values[i].isNaN {
let dataEntry = ChartDataEntry(value: Double(values[i]), xIndex: i)
dataEntries.append(dataEntry)
}
}
let lineChartDataSet = LineChartDataSet(yVals: dataEntries, label: "Label")
let lineChartData = LineChartData(xVals: labels, dataSet: lineChartDataSet)
lineChartView.data = lineChartData
}
The solution which worked for me is splitting Linedataset into 2 Linedatasets. First would hold yvals till empty space and second after emptyspace.
//create 2 LineDataSets. set1- till empty space set2 after empty space
set1 = new LineDataSet(yVals1, "DataSet 1");
set2= new LineDataSet(yVals2,"DataSet 1");
//load datasets into datasets array
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
dataSets.add(set1);
dataSets.add(set2);
//create a data object with the datasets
LineData data = new LineData(xVals, dataSets);
// set data
mChart.setData(data);

Lucene Highlighter class: highlight different words in different colors

Probably most people reading the title who know a bit about Lucene won't need much further explanation. NB I use Jython but I think most Java users will understand the Java equivalent...
It's a classic thing to want to do: you have more than one term in your search string... in Lucene terms this returns a BooleanQuery. Then you use something like this code to highlight (NB I am a Lucene newbie, this is all closely tweaked from Net examples):
yellow_highlight = SimpleHTMLFormatter( '<b style="background-color:yellow">', '</b>' )
green_highlight = SimpleHTMLFormatter( '<b style="background-color:green">', '</b>' )
...
stream = FrenchAnalyzer( Version.LUCENE_46 ).tokenStream( "both", StringReader( both ) )
scorer = QueryScorer( fr_query, "both" )
fragmenter = SimpleSpanFragmenter(scorer)
highlighter = Highlighter( yellow_highlight, scorer )
highlighter.setTextFragmenter(fragmenter)
best_fragments = highlighter.getBestTextFragments( stream, both, True, 5 )
if best_fragments:
for best_frag in best_fragments:
print "=== best frag: %s, type %s" % ( best_frag, type( best_frag ))
html_text += "&bull %s<br>\n" % unicode( best_frag )
... and then the html_text is put in a JTextPane for example.
But how would you make the first word in your query highlight with a yellow background and the second word highlight with a green background? I have tried to understand the various classes in org.apache.lucene.search... to no avail. So my only way of learning was googling. I couldn't find any clues...
I asked this question four years ago... At the time I did manage to implement a solution using javax.swing.text.html.HTMLDocument. There's also the interface org.w3c.dom.html.HTMLDocument in the standard Java library. This way is hard work.
But for anyone interested there's a far simpler solution. Taking advantage of the fact that Lucene's SimpleHTMLFormatter returns about the simplest imaginable "marked up" piece of text: chosen words are highlighted with the HTML B tag. That's it. It's not even a "proper" HTML fragment, just a String with <B>s and </B>s in it.
A multi-word query generates a BooleanQuery... from which you can extract multiple TermQuerys by going booleanQuery.clauses() ... getQuery()
I'm working in Groovy. The colouring I want to apply is console codes, as per BASH (or Cygwin). Other types of colouring can be worked out on this model.
So you set up a map before to hold your "markup details":
def markupDetails = [:]
Then for each TermQuery, you call this, with the same text param each time, stipulating a different colour param for each term. NB I'm using Lucene 6.
def createHighlightAndAnalyseMarkup( TermQuery tq, String text, String colour ) {
def termQueryScorer = new QueryScorer( tq )
def termQueryHighlighter = new Highlighter( formatter, termQueryScorer )
TokenStream stream = TokenSources.getTokenStream( fieldName, null, text, analyser, -1 )
String[] frags = termQueryHighlighter.getBestFragments( stream, text, 999999 )
// not sure under what circs you get > 1 fragment...
assert frags.size() <= 1
// NB you don't always get all terms in all returned LDocuments...
if( frags.size() ) {
String highlightedFrag = frags[ 0 ]
Matcher boldTagMatcher = highlightedFrag =~ /<\/?B>/
def pos = 0
def previousEnd = 0
while( boldTagMatcher.find()) {
pos += boldTagMatcher.start() - previousEnd
previousEnd = boldTagMatcher.end()
markupDetails[ pos ] = boldTagMatcher.group() == '<B>'? colour : ConsoleColors.RESET
}
}
}
As I said, I wanted to colourise console output. The colour parameter in the method here is per the console colour codes as found here, for example. E.g. yellow is \033[033m. ConsoleColors.RESET is \033[0m and marks the place where each coloured bit of text stops.
... after you've finished doing this with all TermQuerys you will have a nice map telling you where individual colours begin and end. You work backwards from the end of the text so as to insert the "markup" at the right position in the String. NB here text is your original unmarked-up String:
markupDetails.sort().reverseEach{ pos, markup ->
String firstPart = text.substring( 0, pos )
String secondPart = text.substring( pos )
text = firstPart + markup + secondPart
}
... at the end of which text contains your marked-up String: print to console. Lovely.

Specify local Dynamic in Grid

I would like to update specific parts of a Grid dynamically in different ways. Consider the following toy example: I have two rows: one must be updated one-by-one (a, b, c), as these symbols depend on different triggers; the second row depends on one single trigger (show) that allows displaying/hiding some data.
Now I know that I can wrap the whole Grid structure into Dynamic, and even specify which symbols to track, thus this example does what I want:
Checkbox[Dynamic[show]]
test = {0, 0};
Dynamic[Grid[{{Dynamic#a, Dynamic#b, Dynamic#c},
If[show, Prepend[test, "test:"], {}]}, Frame -> All],
TrackedSymbols :> {show}]
Though for certain reasons I would like to have a locally specified Dynamic, that is only applied to the second row of the Grid.
For those who are wondering what ungodly situation would it be, just imagine the followings: show is used in any of a, b or c, and these I do NOT want to update when show is changing, their changes depend on other triggers. Why not remove then show from the symbols of the first row? Imagine, I can't, as show is present in a function that is used in a, b or c, and this function I cannot access easily.
Of course wrapping the first argument of If into Dynamic won't help here, as the Grid itself or any of its cells won't become dynamic:
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
If[Dynamic#show, Prepend[test, "test:"], {}]
}, Frame -> All]
Furthermore, wrapping a row into Dynamic makes the given row invalid, as it does not have head List anymore:
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
Dynamic#If[show, Prepend[test, "test:"], {}]
}, Frame -> All]
Mapping Dynamic over the row does not work either because show is not updated dynamically:
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
Dynamic /# If[show, Prepend[test, "test:"], {}]
}, Frame -> All]
Also, wrapping Dynamic[If[...]] around list members work, but now I have to evaluate If 3 times instead of just 1.
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
Dynamic[If[show, #, ""]] & /# Prepend[test, "test:"]
}, Frame -> All]
Would like to know if there is any solution to overcome this particular problem by locally applying a Dynamic wrapper on a row.
Here is a solution using the Experimental ValueFunction
show = True;
test = {0, 0};
Checkbox[Dynamic[show]]
Now write your own little Dynamic update function on the side
Needs["Experimental`"];
row = {};
updateRow[x_, v_] := row = If[v, Prepend[test, "test:"], {}];
ValueFunction[show] = updateRow;
Now make the Grid, and now can use Dynamic on EACH row, not around the whole Grid, which is what you wanted:
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
{Dynamic#row}
},
Frame -> All
]
ps. I just read a post here by telefunkenvf14 that mentions this package and this function, which I did not know about, and when I saw this function, I remembered this question, and I thought it should be possible to use that function to solve this problem.
ps. I need to work more on placing the grid row correctly....
update(1)
I can't figure how to splice the final row over the columns in the grid. Which is strange, as it has List head, yet it won't go across all the columns. It will only go in the first cell. Tried Sequence, SpanFromLeft, and such, but no luck. May be someone can figure this part out.
Here is my current trial:
Needs["Experimental`"];
row = {};
updateRow[x_, v_] := row = If[v, {"test:", 0, 0}, {}];
ValueFunction[show] = updateRow;
show = False;
Checkbox[Dynamic[show]]
f = Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
List#Dynamic[row]
},
Frame -> All
]
It seems it should be doable. I do not see what is the problem now...
update(2)
As a temporary solution, I split the second row by force before hand. This made it possible to do what I want. Not sure if this meets the OP specifications or not (my guess is that it does not), but here it is:
Needs["Experimental`"];
ra = 0;
rb = 0;
rc = 0;
updateRow[x_, v_] :=
row = If[v, ra = "test:"; rb = 0; rc = 0, ra = ""; rb = ""; rc = ""]
ValueFunction[show] = updateRow;
show = False;
Checkbox[Dynamic[show]]
f = Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
{Dynamic#ra, Dynamic#rb, Dynamic#rc}
},
Frame -> All]
This is actually a comment on #Nasser's solution and suggested fix to avoid manual splitting of the second row, but because of space limitations in the comment area, I post it as answer. Will be happy to delete it as soon as Nasser confirms that it works and incorporates it into his answer.
The clue to a solution is found in the Possible Issues section of Item in the documentation:
If Item is not the top-most item in the child of a function that supports Item, it will not work.
I use this to modify #Nasser's solution in the following way. First, I need to change the definition of row so that for both values of show the length of row is the same.
Needs["Experimental`"];
row = {"", "", ""};
updateRow[x_, v_] := row = If[v, Prepend[test, "test:"], {"", "", ""}];
Experimental`ValueFunction[show] = updateRow;
The second change needed is to wrap each element of Dynamic#row with Item:
Grid[{{Dynamic#a, Dynamic#b, Dynamic#c},
{Item[Dynamic#row[[1]]], Item[Dynamic#row[[2]]],
Item[Dynamic#row[[3]]]}}, Frame -> All]
Edit: Item wrapper is not really needed; it works just as well without it:
Grid[{{Dynamic#a, Dynamic#b, Dynamic#c},
{Dynamic#row[[1]], Dynamic#row[[2]],
Dynamic#row[[3]]}}, Frame -> All]

How can I do a padding between my highest x-value and the plot's right gap in Highcharts?

I need to delete the margins between my lines and plot gap.
I decided to use the startOnTick and endOnTick property but in this case line's points in the gap are not seen or seen only part of them.
Please, help if you know how, of course)))
You can set maxPadding and minPadding within chart options provided to the constructor.
Or you can use setExtremes(min, max) after instantiate the chart for dynamic values.
var myChart = new Highchart.chart(options),
extremes = myChart.xAxis[0].getExtremes(),
minPadding = 20,
maxPadding = 20;
myChart.xAxis[0].setExtremes(extremes.dataMin - minPadding, extremes.dataMax + maxPadding);