Generating image in elixir with text - imagemagick

I would like the same what this post is asking for: Generating initials avatar with Elixir
The answer to use Mogrify is not very helpfull. I already got https://github.com/zamith/mogrify_draw/ but it is not generating the text I want.
The examplecode
%Mogrify.Image{path: "test.png", ext: "png"}
|> custom("size", "280x280")
|> canvas("white")
|> custom("fill", "blue")
|> Mogrify.Draw.circle(140,140,100,100)
|> custom("fill", "yellow")
|> Mogrify.Draw.circle(140,140,140,100)
|> create(path: ".")
is creating the image with the circles.
I tried
%Mogrify.Image{path: "test.png", ext: "png"}
|> custom("size", "280x280")
|> canvas("white")
|> Mogrify.Draw.text(10, 10, "Text")
|> create(path: ".")
but this is only creating a blank white picture. Any ideas what I am doing wrong?
Thank you.

Related

How to reverse each string in a string list at \n?

I have this function which first reads the content of some files, then I have made the contents of the files into separate strings in a list. Then I want to access each element in the list and split the string when \n appears and reverse it. However I haven't been able to do the last part. How do I split each string in a string list when it comes across \n and then reverse the content?
An example. If I have a file that says "aaa\nbbb\n" and another that say "ccc\nddd\n" I want to split the string at \n at make the string says "ddd\nccc\nbbb\naaa\n "
Right now the output of the code underneath is Some "ccc\nddd\naaa\nbbb\n"
let tac (filenames:string list) : string option =
let bal = List.map (fun x -> readFile(x)) filenames
let mutable ral = []
for elem in bal do
let wal = [elem.Value]
ral <- ral # wal
let sal = List.choose id ral |> List.rev |> String.concat """"""
try
Some(sal)
with
| _ -> None
To be able to run your code, I simplified it slightly, so I have just:
let bal = ["aa\nbb"; "cc\ndd"]
let mutable ral = []
for elem in bal do
let wal = [elem]
ral <- ral # wal
let sal = bal |> List.rev |> String.concat ""
It seems that your code is also using option values in some way, but that's not relevant to this question. I also replace """""" with much simpler "". In your original code, you also have:
try Some(sal) with _ -> None
This is not necessary, because Some(sal) can never throw an exception. Now, in the code shown above, you have a for loop and then you use List.rev. The for loop is just recreating the same list, so this is not making much sense. You could either change the loop to reverse the list and drop List.rev or you could drop List.rev. I'll do the former:
let bal = ["aa\nbb"; "cc\ndd"]
let sal = bal |> List.rev |> String.concat ""
This takes a list of strings, reverses it and then concatenates the strings in reversed order. You also want to reverse each string. To do this, you can take characters of the string, reverse them and then turn them into strings and concatenate those:
"abc" |> Seq.rev |> Seq.map string |> String.concat ""
To do this for all strings in your original list, you can use List.map:
let sal =
bal
|> List.map (fun s ->
s |> Seq.rev |> Seq.map string |> String.concat "")
|> List.rev |> String.concat ""

F# sort by indexes

Let's say I have two lists:
let listOfValues = [100..105] //can be list of strings or whatever
let indexesToSortBy = [1;2;0;4;5;3]
Now I need listOfValues_sorted: 102;100;101;105;103;104
It can be done with zip and "conversion" to Tuple:
let listOfValues_sorted = listOfValues
|> Seq.zip indexesToSortBy
|> Seq.sortBy( fun x-> fst x)
|> Seq.iter(fun c -> printfn "%i" (snd c))
But I guess, there is better solution for that?
I think your solution is pretty close. I would do this
let listOfValues_sorted =
listOfValues
|> Seq.zip indexesToSortBy
|> Seq.sortBy fst
|> Seq.toList
|> List.unzip
|> List.head
you can collapse fun x -> fst x into simply fst. And then unzip and get what ever list you want
If indexesToSortBy is a complete set of indexes you could simply use:
indexesToSortBy |> List.map (fun x -> listOfValues |> List.item x )
Your example sounds precisely what the List.permute function is for:
let listOfValues = [100..105]
let indexesToSortBy = [|1;2;0;4;5;3|] // Note 0-based indexes
listOfValues |> List.permute (fun i -> indexesToSortBy.[i])
// Result: [102; 100; 101; 105; 103; 104]
Two things: First, I made indexesToSortBy an array since I'll be looking up a value inside it N times, and doing that in a list would lead to O(N^2) run time. Second, List.permute expects to be handed a 0-based index into the original list, so I subtracted 1 from all the indexes in your original indexToSortBy list. With these two changes, this produces exactly the same ordering as the let listOfValues_sorted = ... example in your question.

Read all lines from file

I want to read all the lines from the file and implement acquired the following:
let s1 = File.ReadAllText("\\test.txt")
let splitArr = s1.Split[|' '|] |> Array.toList
let checkList = check splitArr
let final = String.concat " " checkList |> toLower |> makeUpper
Console.Write(final)
I even tried to looping through the file but perhaps did wrong:
let myfile = File.OpenText("\\test.txt")
let fileLoop() =
let s1 = myfile.ReadLine()
let splitArr = s1.Split[|' '|] |> Array.toList
let checkList = check splitArr
let final = String.concat " " checkList |> toLower |> upper
Console.Write(s1)
while fileLoop() do ignore None
Your existing code bears little resemblance with your textual description of what you are trying to achieve. Ignoring that, a simple observation to make your current code work: You are using File.ReadAllText, which returns a giant blob of text - but you are afterwards assuming it comes already separated by lines. Use one of the methods in the File module that returns the text linewise, that is ReadLines or ReadAllLines. Try the following:
File.ReadLines("\\test.txt")
|> Seq.iter (fun s1 ->
let splitArr = s1.Split[|' '|] |> Array.toList
let checkList = check splitArr
let final = String.concat " " checkList |> toLower |> makeUpper
Console.WriteLine(final)
)
Or making heavier use of pipes:
File.ReadLines "\\test.txt"
|> Seq.iter (fun s1 ->
s1.Split [|' '|]
|> Array.toList
|> check
|> String.concat " "
|> toLower
|> makeUpper
|> Console.WriteLine
)

How to filter rows using Deedle

In order to get comfortable with Deedle I made up a CSV file that represents a log of video rentals.
RentedOn,Shop,Title
12/dec/2013 00:00:00,East,Rambo
12/dec/2013 00:00:00,West,Rocky
12/dec/2013 00:00:00,West,Rambo
12/dec/2013 00:00:00,East,Rambo
13/dec/2013 00:00:00,East,Rocky
13/dec/2013 00:00:00,East,Rocky
13/dec/2013 00:00:00,East,Rocky
14/dec/2013 00:00:00,West,Rocky 2
I have the following function, that groups the rentals by Shop (East or West):
let overview =
__SOURCE_DIRECTORY__ + "/rentallog.csv"
|> Frame.ReadCsv
|> Frame.groupRowsByString "Shop"
|> Frame.nest
|> Series.map (fun dtc df ->
df.GetSeries<string>("Title") |> Series.groupBy (fun k v -> v)
|> Frame.ofColumns |> Frame.countValues )
|> Frame.ofRows
I'd like to be able to filter the rows by the date in the RentedOn col, however, I'm not sure how to do this. I know its probably using the Frame.filterRowValues function but I'm unsure the best way to use this. Any guidance on how to filter would be appreciated.
Update based on #jeremyh advice
let overview rentedOnDate =
let addRentedDate (f:Frame<_,_>) =
f.AddSeries ("RentedOnDate", f.GetSeries<DateTime>("RentedOn"))
f
__SOURCE_DIRECTORY__ + "/rentallog.csv"
|> Frame.ReadCsv
|> addRentedDate
|> Frame.filterRowValues (fun row -> row.GetAs<DateTime>("RentedOnDate") = rentedOnDate)
|> Frame.groupRowsByString "Shop"
|> Frame.nest
|> Series.map (fun dtc df ->
df.GetSeries<string>("Title") |> Series.groupBy (fun k v -> v)
|> Frame.ofColumns |> Frame.countValues )
|> Frame.ofRows
Thanks,
Rob
Hey I think that you might get a faster answer if you add an f# tag to your question too.
I used the following link to answer your question which has some helpful examples.
This is the solution I came up with. Please note that I added a new column RentedOnDate that actually has a DateTime type that I do the filtering on.
let overview rentedOnDate =
let rentalLog =
__SOURCE_DIRECTORY__ + "/rentallog.csv"
|> Frame.ReadCsv
rentalLog
|> Frame.addSeries "RentedOnDate" (rentalLog.GetSeries<DateTime>("RentedOn"))
|> Frame.filterRowValues (fun row -> row.GetAs<DateTime>("RentedOnDate") = rentedOnDate)
|> Frame.groupRowsByString "Shop"
|> Frame.nest
|> Series.map (fun dtc df ->
df.GetSeries<string>("Title") |> Series.groupBy (fun k v -> v)
|> Frame.ofColumns |> Frame.countValues )
|> Frame.ofRows
// Testing
overview (DateTime.Parse "12/dec/2013 00:00:00")

F# List of random numbers concatenated

Can someone tell me why this works
let createRandomList = List.init 9 (fun _ -> randomNumberGenerator.Next(0,9))
let concatRandomList =
createRandomList
|> Seq.map string
|> String.concat ""
and this does not?
let createConcatRandomList = List.init 9 (fun _ -> randomNumberGenerator.Next(0,9))
|> Seq.map string
|> String.concat ""
I am getting an "Incomplete value or function definition" on the second code block
Thanks in advance
In the second example you need to indent the |> to the same level as List

Resources